Skip to content

"Self" type arguments lead to confusing error messages #52204

Open
@Hixie

Description

@Hixie

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...)

Metadata

Metadata

Assignees

No one assigned

    Labels

    legacy-area-front-endLegacy: Use area-dart-model instead.model-messagesPoor/undesirable messaging in errors/warnings emitted by the analyzer and/or CFE.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions