-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Type error in generic closure #42763
Comments
Here's a reproducible case not involving Flutter: typedef ValueCallback<T> = void Function(T value);
void main() {
BugReport<String> bugReport = BugReport<String>((String value) {
print(value);
});
bugReport.createOtherClass();
}
class BugReport<T> {
const BugReport(this.onValue);
final ValueCallback<T> onValue;
OtherClass<T> createOtherClass() {
OtherClass<T> result = OtherClass<T>(this);
result.init();
return result;
}
}
class OtherClass<T> {
OtherClass(this._bugReport);
BugReport _bugReport;
void init() {
print(_bugReport.onValue);
}
} Result: $ dart main.dart
Unhandled exception:
type '(String) => Null' is not a subtype of type '(dynamic) => void'
#0 OtherClass.init (file:///Users/tvolkert/project/bugreport/main.dart:28:22)
#1 BugReport.createOtherClass (file:///Users/tvolkert/project/bugreport/main.dart:17:12)
#2 main (file:///Users/tvolkert/project/bugreport/main.dart:7:13)
#3 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:301:19)
#4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
|
The problems here, in both the Flutter and Dart examples, are that the declarations of - class _BugReportState<T> extends State<BugReport> {
+ class _BugReportState<T> extends State<BugReport<T>> {
} class OtherClass<T> {
OtherClass(this._bugReport);
- BugReport _bugReport;
+ BugReport<T> _bugReport
void init() {
print(_bugReport.onValue);
}
} Since T is dynamic, this leads to the type of the value callback being inferred as |
Well spotted, sir! Closing as working as intended. |
Here's another thing which is worth keeping in mind: Even when the type arguments have been added, it is unsafe to have an instance variable like typedef F<X> = void Function(X);
class C<X> {
F<X> f; // `F` is contravariant in its type parameter: not recommended.
C(this.f);
}
void main() {
C<num> c = C<int>((x) {});
c.f; // Throws.
} The evaluation of The essence of the problem is that For now, it's best to avoid contravariant instance variables whenever possible. If it cannot be avoided, it may be possible to maintain the required discipline manually (that is, never use a |
Steps to reproduce
Expected behavior
You expect no errors in running this code
Actual behavior
The following error is thrown:
Other information
The text was updated successfully, but these errors were encountered: