Sdk: Error inferring type in the abstract class constructor

Created on 31 Jan 2020  路  9Comments  路  Source: dart-lang/sdk

I stumbled upon this case when working with abstract classes:

abstract class Test {
  final String value;

  Test(this.value); // [1]
}

abstract class Test2 {
  final String value;

  Test2(String i) : value = i; // [2]
}

class Store {}

class AppController = Test with Store;
class AppController2 = Test2 with Store;

void main() {
  var test1 = AppController(inject()); // prints 'dynamic'
  var test2 = AppController2(inject()); // prints 'String'
}

T inject<T>() {
  print(T);
}

The only difference between those two classes are the constructor signatures. The first one, Test, uses the this. shorthand; the second one, Test2, does not. I expected the behaviour to be the same, but Dart is actually inferring the wrong runtime type. I know that if I write inject<String>() it will work; I would like to understand why it doesn't work without it, even though Test.value is of type String.

View in DartPad

P1 area-front-end type-bug

Most helpful comment

Changing [1] to Test(String this.value); makes a difference too. Seems like a bug, since the parameter types should be inferred as the type of the field they're initializing.

All 9 comments

Changing [1] to Test(String this.value); makes a difference too. Seems like a bug, since the parameter types should be inferred as the type of the field they're initializing.

@ds84182 I think you're right. I work with the flutter_modular that needs dependency injection and I always have to type it that way in abstract constructors (in the case of MobX).

Congratulations to @savioserra for identifying this error.

Congratulations bro, I was suffering from this error and could not understand what it was. Very good @savioserra to identifying this error.

Thank you @Bwolfs2 and @jacobaraujo7 , but we know it was a team effort. I hope we can solve this issue as soon as possible :)

Great Job!!!!

I've never thought that was a bug, but it's make a sense. I guessed it was just a very strange behavior.

@ds84182 Also, (String this.value) gives you a warning, since we don't need to type it manually. So I do think it is a bug.

This is a CFE issue. The type of the constructor's parameter does not forward correctly with a mixin application if the constructor is initializing a field. This manifests as an implicit downcast in some cases, and soundness violation in others. Minimal test case:

abstract class Foo {
  final String field;
  Foo(this.field);
}

mixin Bar {}

class FooImpl = Foo with Bar;

void main() {
  FooImpl(1234).field.trim(); // Error in analyzer, no error in CFE, soundness violation in the VM and JS.
}

cc @lrhn, because I don't know who else to forward this to ^^;

@ds84182 Thank you so much for your help

Was this page helpful?
0 / 5 - 0 ratings