Skip to content

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

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

Open
Hixie opened this issue Apr 27, 2023 · 0 comments
Open

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

Hixie opened this issue Apr 27, 2023 · 0 comments
Labels
legacy-area-front-end Legacy: Use area-dart-model instead. model-messages Poor/undesirable messaging in errors/warnings emitted by the analyzer and/or CFE.

Comments

@Hixie
Copy link
Contributor

Hixie commented Apr 27, 2023

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

@mraleph mraleph added the legacy-area-front-end Legacy: Use area-dart-model instead. label Apr 28, 2023
@johnniwinther johnniwinther added the model-messages Poor/undesirable messaging in errors/warnings emitted by the analyzer and/or CFE. label Nov 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
legacy-area-front-end Legacy: Use area-dart-model instead. model-messages Poor/undesirable messaging in errors/warnings emitted by the analyzer and/or CFE.
Projects
None yet
Development

No branches or pull requests

3 participants