Description
Consider the following program (variant of example given in #33805):
class A<X extends A<X>> {}
X testme<X>() { print(X); return null; }
main() {
A a1 = testme<A<dynamic>>();
A a2 = testme<A<A<dynamic>>>();
A a3 = testme();
}
The response from dartanalyzer
looks as follows:
$ dartanalyzer --preview-dart-2 --no-hints n003.dart
Analyzing n003.dart...
error • 'dynamic' doesn't extend 'A' at n003.dart:8:19 • type_argument_not_matching_bounds
error • 'A' doesn't extend 'A<A>' at n003.dart:9:19 • type_argument_not_matching_bounds
error • 'dynamic' doesn't extend 'A' at n003.dart:9:21 • type_argument_not_matching_bounds
3 errors found.
$ dartanalyzer --version
dartanalyzer version 2.0.0-dev.68.0
In the first line of main
, we are passing the type argument A<dynamic>
to the invocation of testme
, and that is in itself a super-bounded type (because A<Null>
is regular-bounded, because Null <: A<Null>
). For testme
there are no constraints on the type argument, and in particular it can be a super-bounded type. So the analyzer should allow this.
The second line of main
is similar, but it illustrates that the analyzer flags an error both for the type argument A<A<dynamic>>
as a whole, and for the nested type argument A<dynamic>
. So none of them are allowed to be a super-bounded type, and they should both be allowed.
With the common front end, the third line gets the inferred type argument A<A<dynamic>>
(the same as in the second line), which can be detected by running the program with the VM, due to print(X)
. With dartanalyzer it is not obvious what the inferred type argument is, but we do not get an error from there.