-
Notifications
You must be signed in to change notification settings - Fork 1.7k
strong_mode_invalid_method_override gets confused with complex type parameters #27546
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
Comments
Possibly related test. This code does not appear to trigger any analyzer errors: import 'package:test/test.dart';
class X {}
class Y extends X {}
class A<U extends X> {
U u;
}
void main() {
test('Asignment through a covariant template throws exception', () {
A<Y> ay = new A<Y>();
A<X> ayAsAx = ay;
expect(() {
ayAsAx.u = new X();
}, throws);
});
} /cc @Hixie |
This actually has nothing directly to do with overrides. The way that we treat uses of generic types where you leave off the arguments (I call these "raw types") has a few warts right now, and a notable one is around uses of raw types as bounds for generic type parameters. The current treatment of In the meantime, you can fix your issue by specifying an argument for class C<T extends A<X>> extends B {
@override
T foo() => null;
} Closing as a duplicate of #27526. |
Just saw your second example, but not sure I understand it: are you expecting an analyzer warning there, and if so where and why? |
Consider this line:
On this line, the field In other type systems, the type system would fail to prove that |
Put a different way, given that a program is well-typed according to strong mode, when does an assignment (or a function call) require a runtime type check on the objects it receives (either as the right-hand side of the assignment or the actual value of a parameter)? |
Right. So, first of all, you are running on the VM, which doesn't yet implement strong mode runtime checks. But it does implement checked mode, and it is the checked mode check that gives you the exception there. If you run that in production mode, you will get no exception. Now to strong mode. Covariant generics are not sound in general. In order to support them, strong mode requires a check everywhere a type variable is used contra-variantly. You can think of this as a subset of the checked mode checks. These checks guarantee that values that actually reach a location have the type expected by that location, so that subsequent uses of the location can assume that it has the right type. Note that these checks are only required for contra-variant uses of generic type parameters. So to your question:
class A {
int x;
int read() => 3;
void write(int x) {}
void callback(void f(int x)) {}
}
class B<T> {
T x;
T read() => null;
void write(T x) {}
void callback(void f(T x)) {}
}
void main() {
A a = new A();
a.x = 3; // no check
int x = a.x; // no check
num y = x; // no check
x = y; // downcast, check
x = a.read(); // no check
a.write(x); // no check
a.callback((int x) => x); // no check,
B<int> b = new B<int>();
b.x = 3; // covariance check (optimizable)
x = b.x; // no check
x = b.read(); // no check
b.write(x); // covariance check (optimizable)
b.callback((int x) => x); // no check, contra-variant
} Note that the implied covariance check on the assignment to
In general, whenever you assign to a field, or pass an argument to a parameter, where the type of the field/parameter uses the class type parameter in a contra-variant position (or is in an override of field/method that does so), there is an implied check (again, subject to optimization). @Sfshaza maybe this should go in a FAQ somewhere? |
Thanks that makes good sense. |
This triggers a
strong_mode_invalid_method_override
on the override offoo
, but that seems spurious. If you remove the<U extends X>
, then the error goes away.The text was updated successfully, but these errors were encountered: