-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Wildcard type bounds #54108
Comments
I can solve the issue by adding this function to bool testAdapter(Table t) => test(t as T); but it would be nice to have type bounds so that this is not required. This is probably a special case of #52826. |
This is use-site variance. It's a way to ensure soundness, that Dart's unsound covariance doesn't protect against. |
Maybe I misunderstand what Java would do in this case then, because my assumption (untested) was that Java would handle this just fine, but Dart doesn't. So how then is Java more restrictive than Dart? |
Duplicate of dart-lang/language#753 |
I am closing the issue because it is a duplicate to the whole web of issues on the language repo, but feel free to continue discussion here.
@lrhn is simply expanding on the topic of wildcards e.g. explains how they work and what kind of restrictions they introduce. "Restrictive" here applies specifically to the things you can do with values of types containing a wildcard. |
Here are a couple of references to related discussions and proposals: We do have a proposal for a simplified kind of use-site variance (namely use-site invariance) in dart-lang/language#229. The simplified feature is a rather good match to Dart, because Dart may well be enhanced with statically checked declaration-site variance, dart-lang/language#524, which will handle most cases in a less verbose and more convenient manner. We have also considered a fully general approach to use-site variance, dart-lang/language#753, but that's perhaps too much mechanism to add if we already have declaration-site variance. Here is the example using declaration-site variance ( class Table {}
class TableSubclass extends Table {}
class Inner<in T extends Table> { // <-- This line was modified.
final bool Function(T) test;
Inner(this.test);
}
class Outer {
final Inner<Table> inner;
Outer(this.inner);
}
void main() {
final inner = Inner<TableSubclass>((t) => true);
print(inner.test(TableSubclass()));
final outer = Outer(inner); // Compile-time error!
print(outer.inner.test(TableSubclass()));
} With this approach, we've changed the class You can read more about "non-covariant members" in dart-lang/language#296 and dart-lang/language#297. If you wish to support the detection of this kind of member you can vote for a lint to flag these members here: dart-lang/linter#4111. So this is a particular trade-off: The class
You can do something in Java which is essentially the same thing as the example above using declaration-site variance, which has the same trade-off. However, let's consider another approach as well, where we preserve the ability of In order to express a property of a class which is similar to class Table {}
class TableSubclass extends Table {}
class Inner<T extends Table> {
final Function<T, Boolean> test;
Inner(Function<T, Boolean> test) {
this.test = test;
}
}
class Outer {
final Inner<? extends Table> inner;
Outer(Inner<? extends Table> inner) {
this.inner = inner;
}
}
public class n001 {
public static void main(String[] args) {
final Inner<TableSubclass> inner = new Inner<TableSubclass>(t -> true);
System.out.println(inner.test(new TableSubclass()));
final Outer outer = new Outer(inner);
System.out.println(outer.inner.test(new TableSubclass()));
}
} This produces an error saying that it cannot find the symbol
What happens here is that Java simply pretends that the unsafe members do not exist, in this case: An This is safe because it prevents any usage of the unsafe member, so we aren't going to get any run-time type errors because of such usages. Of course, it won't do the job because you can't really use the Dart could have done a similar thing, of course (Dart was created several years after wildcards were added to Java, and the whole set of issues was very well-known at the time), but Dart chose to allow the unsafe operations at compile time and check them at run time. This is usually working quite fine, but these "non-covariant members" (like As an aside, I should mention that it is possible to handle the situation where an object |
Java has wildcard type bounds, e.g.
? extends SomeClass
. Dart does not.This can cause runtime type errors in Dart for people like me who have a hard time reasoning through covariance...
For example
This prints
Whereas if you change
Outer
tothe output is
This seems to indicate that you should be able to do
but wildcard type bounds are not supported in Dart.
This becomes more important when
inner
is not a single value, but a list:List<Inner<Table>> inners
-- since with a list of arbitrary length, you can't just impose a fixed number type bounds on the surrounding class. You should be able to doList<Inner<? extends Table>> inners
in this case.The text was updated successfully, but these errors were encountered: