-
Notifications
You must be signed in to change notification settings - Fork 26.8k
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
Confusing error message: type '_Future' is not a subtype of type 'Future<bool>' #15654
Comments
Hi @lovasoa could you share a more detailed snippet of the code that is causing this? |
I have a class that extends
And the signature of _setBluetoothState is
. The variable
|
Important note: I get this error only on flutter master, not in the beta channel. |
Thanks for the details. You're seeing this on Unfortunately this has introduced some breaking changes, in your case the issue is that The solution would be for the plugin to change the implementation of Future<bool> get isOn => _channel.invokeMethod('isOn'); To: Future<bool> get isOn async {
final bool isOn = await _channel.invokeMethod('isOn');
return isOn;
} This is a third party plugin, I've opened an issue on FlutterBlue's repository to bring it to their attention. |
But shouldn't this be a compile-time error rather than a runtime error, then ? |
I believe you still need to pass the
|
@lovasoa It is not a compile time error because assigning an expression of type Future<dynamic> foo() {
return new Future<dynamic>.value(10);
}
Future<String> bar() {
return foo(); // will throw in runtime, no errors in compile time
// this is the same as: return foo() as Future<String>;
} You can make analyzer report errors in such places if you add For more information about Dart 2 breaking changes see this announcement on flutter-dev. Hope this clarifies things a bit. I do agree that an error message could be made better. I have filed dart-lang/sdk#32564 to address this. |
@mraleph Thank you for the informative answer ! But I am still a little confused. In your example, there is indeed a type issue: the value inside the Future returned by So where does the error come from ? I think the code should either not compile, or compile and work as long as the dynamic value actually has the expected type. What is the point of compiling a code that can only fail ? |
Let me amend my example a bit: Future<dynamic> foo() {
return new Future(() => something ? 11 : “abc”);
}
|
Yes, but in your example, I would expect the runtime error to be raised only when |
@lovasoa type of Additionally you can take Here is a more expanded example: Future<dynamic> foo1({bool intValue}) {
return new Future<dynamic>(() => intValue ? 10 : "abc");
}
Future<dynamic> foo2({bool intValue}) {
return intValue ? new Future<int>.value(10) : new Future<String>.value("abc");
}
void canHandleAnything(Future<dynamic> f) {
f.then((dynamic value) => print(value));
}
Future<int> canHandleOnlyInts(Future<int> f) {
return f.then((int x) => x * 10);
}
// Perfectly fine: passing Future<dynamic> to a function that expects Future<dynamic>
canHandleAnything(foo1(intValue: true));
canHandleAnything(foo1(intValue: false));
// throws: can't pass Future<dynamic> to a function that expects Future<int>
// even if Future<dynamic> in the end might end up producing int.
canHandleOnlyInts(foo1(intValue: true));
canHandleOnlyInts(foo1(intValue: false));
// Perfectly fine: passing Future<int> or Future<String> to a function that expects Future<dynamic>
canHandleAnything(foo2(intValue: true));
canHandleAnything(foo2(intValue: false));
// Perfectly fine: passing Future<int> to a function expecting Future<int>
// Note that here Future<int> is "hiding" inside the expression of type Future<dynamic>
canHandleOnlyInts(foo2(intValue: true));
// throws: can't pass Future<String> to a function expecting Future<int>
// Note that here Future<int> is "hiding" inside the expression of type Future<dynamic>
canHandleOnlyInts(foo2(intValue: false)); In other words if you have an expression of type Which means when you do assignment like this Future<dynamic> v0 = ...;
Future<String> v1 = v0; you can't know whether assignment will fail or not in compile time. Now, how did things work before? In Dart 1 you could have taken // Valid Dart 1 code that throws nothing in runtime. v contains a value of type Future<dynamic>.
Future<int> fu = foo1(intValue: false);
// This would throw only when fu completes and it tries to invoke closure that expects
// int value with a string argument.
fu.then((int x) => x * 10); In Dart 1 if you have a variable of type |
Thank you very much for this explanation! The thing I did not understand was that even if |
I also faced same type of issue, i just added async to the function. It works for me!! |
The original issue here is that the flutterBlue library needs to be updated for Dart2. Since that's not a Flutter issue, I'm going to close this bug. |
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of |
Steps to Reproduce
Calling
FlutterBlue.instance.isOn
from the flutterBlue library.Logs
Flutter Doctor
The text was updated successfully, but these errors were encountered: