-
Notifications
You must be signed in to change notification settings - Fork 205
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Soft covariance modifier #4177
Comments
This feels related to the safe cast There have been requests for a void foo(Object? arg as int){...} which accepts any argument, but throws if the value is not a I would allow a non- class Foo {
void and(covariant? Foo other) => other != null && ... The parameter is non- We would change collection methods to, fx, bool contains(covariant T value); Since every implementation will still accept (Would this feature be moot with variance annotations? I think it won't, because declaration-site variance isn't powerful enough to handle these cases without making the type invariant. That's too breaking without use-site variance.) |
Yes, that's exactly what led me to use
I considered that briefly, but I worry that this would be really confusing: class Foo {
void method(covariant? String s) {
print(s.length); // Compile error, can't access length on nullable "s".
}
}
That's something I've been wondering about for a long time. I would love to be in a world where we don't need the weird hacky |
We're working on supporting enum-like shorthands (#357) to eliminate some verbosity when accessing a static member on a type where the surrounding context happens to be that same type.
Unfortunately, the very first example in that issue and the first comment are places where using the context type doesn't actually help:
==
,.contains()
, and.containsAll()
. In all of those APIs, the context type is eitherObject
orList<Object>
and not a more precise type that the user might expect.These looser types have been a source of user bugs for years which is why we added lints for unrelated_type_equality_checks, iterable_contains_unrelated_type, and collection_methods_unrelated_type.
These APIs are designed to accept looser types deliberately. Accepting
Object
on the right-hand side of==
means that when an instance of that type is used in a heterogeneous map or set, it won't throw exceptions when compared to unrelated types. Likewise, allowing looser types in the collection methods means the methods still work when collections are used in a covariant way:This program prints "false" instead of throwing an exception, which is what would happen if the parameter type of
contains()
wasE
.Is there a way to get the runtime flexibility around heterogeneous collections and when using collections in covariant ways while getting having a less error-prone API with stricter static typing?
Proposal
I propose we add a "soft covariant" modifier,
covariant?
. It behaves similarly to the existingcovariant
modifier. It allows a parameter in a method override to have a more precise type than the parameter it overrides.But unlike
covariant
, instead of immediately throwing at runtime if the argument doesn't match the parameter type, it simply passesnull
. This means that the parameter's type must be a nullable type.For example:
When a class implements
==
, we recommend that they usecovariant?
like so:Likewise, we change the signatures of the collection methods to:
This way, when calling these methods, they are statically type checked at the expected element's type without any need for a lint. Also, when the shorthand syntax is supported, it becomes available in the arguments to these methods.
Unfortunately, this doesn't help with
containsAll()
andremoveAll()
. For those, we probably don't want the method to immediately reject an argument collection whose reified type argument isn't precise enough. What actually matters is the elements inside the collection.If we can live without that, then this feature might give us a more general-purpose language mechanism that lets object-oriented APIs be more precisely typed while playing nicely with covariance (at least, as much as it's possible to play nice with such a weird feature).
The text was updated successfully, but these errors were encountered: