Description
Sometimes you need a class which will have subtypes but you need the "Self" type, e.g. so you can have an API that always talks in terms of the same object. One way to do that is to have the superclass have a type argument defined like this:
abstract class Foo<Self extends Foo<Self>> { }
Now subclasses have to specify themselves as the type argument:
class BarFoo extends Foo<BarFoo> { }
If they don't specify any type, they get an error:
class BarFoo extends Foo { }
// error: 'Foo<dynamic>' doesn't conform to the bound 'Foo<Foo<dynamic>>' of the type parameter 'Self'
Other classes can use this abstract type as a generic type argument:
class Baz<T extends Foo<T>> {
Baz(this.test);
final T test;
}
...and type inference works fine:
void main() {
Baz(BarFoo());
}
Sometimes, though, there isn't anything in the equivalent of Baz
to help the type inference; e.g.:
class Baz<T extends Foo<T>> {
Baz(this.test);
final T? test;
}
void main() {
Baz(null);
// error: 'Null' doesn't conform to the bound 'Foo<Null>' of the type parameter 'T'
// error: Couldn't infer type parameter 'T'
// Tried to infer 'Null' for 'T' which doesn't work:
// Type parameter 'T' is declared to extend 'Foo<T>' producing 'Foo<Null>'.
// The type 'Null' was inferred from:
// Parameter 'test' declared as 'T?'
// but argument is 'Null'.
// Consider passing explicit type argument(s) to the generic.
}
I guess I don't know what I would propose instead. I don't know if we can reliably detect this kind of situation but it would be nice to have a message like:
// error: Couldn't infer type parameter 'T' of Baz; consider explicitly providing a subclass of 'Foo'.
(I suppose maybe this is really just a long-winded argument for us introducing an explicit Self
type...)