-
Notifications
You must be signed in to change notification settings - Fork 227
Description
(Please feel free to update the title with a more descriptive one.)
Repro from @mraleph:
class A<T> {}
class B<T> extends A<T> {}
Type typeOf<T>(T v) => T;
void main() {
B<String>? b;
print(typeOf(b ?? A()));
}
Here ideally we want to see String, but it prints dynamic instead.
So in b ?? A(), the type parameter of A is inferred as dynamic instead of String even though type of b is B<String>.
In practice, this causes a lot of headache in a change in the protobuf library. Recently we made a change to return more precise types in generated message classes. Instead of List<T>, we now return PbList<T>. PbList<T> extends ListBase<T> which implements List<T>.
This change caused a lot of breakage in user code, because a lot of types became dynamic after this change.
The fix is not always trivial: we have to add type annotations, but sometimes the types are not even in scope, and sometimes we can't even import the types because they're not exported in a direct dependency.
The fix is also triggers the omit_local_variable_types lint, which shouldn't be a lint as it changes semantics (without type annotations, the element type becomes dynamic).
The changes needed in user code can be seen in cl/809933607. There are two kinds of code that breaks with this change:
-
myMessage?.myList ?? [] -
var myList = myMessage.myList; // PbList<T> ... if (...) { myList = [...]; // List<T> }