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.
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
Most helpful comment
Changing
[1]toTest(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.