-
Notifications
You must be signed in to change notification settings - Fork 196
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
Ternary operator can not infer return type FutureOr #2432
Comments
[Edit: The first version of my comment was wrong. Here's a better one.] The static type of a conditional expression This case was actually discussed, and then omitted from UP, because we strive to avoid introducing The rules which we could have adopted go as follows:
We could also use a less permissive version:
These rules might be better at matching the cases where "it should obviously work", but it also takes a way a set of cases which are just as sound, and "almost as obvious". In the end we decided that it's better to omit these rules. |
@leafpetersen, we should have an old discussion about this in some issue, but I couldn't find it. Does it match your recollection of the situation? |
This seems like our usual problem coming from not propagating the context type into the branches, and doing UP when there is a context type that both branches are (should be) assignable to. If instead we pushed the context type into each branch, then we'll get a compile-time error if either branch is not assignable to the context type. If we don't, we know that both branches have types assignable to the context type, in which case no UP is needed, we can just use the context type as static type. If there is no context type, we do need to find the UP of the two branches, but it can't be wrong then (just imprecise). |
The "try each branch separately" approach doesn't really help us inferring the type of var x = aBoolExpression ? "1" : Future.value("1"); This is of course an example of the case where there is no information in the context type, but the underlying problem is that we can't always try each branch separately when we just need to find a type for an expression. For instance, the context type could be non-trivial (here: List<X> listify<X>(X x) => [x];
void main() {
var y = listify(aBoolExpression ? "1" : Future.value("1"));
} The type of the expression |
True, some context types do not provide a constraint, so they won't help with constraining the type of the branch expressions. It will still find |
It sounds like you're suggesting that we should add those cases to UP after all:
.. and then possibly say that they can only be used if the context type is |
Probably another issue, but maybe this: dart-lang/sdk#49553? |
Thanks for pointing that out! However, it's not quite the topic I was looking for: dart-lang/sdk#49553 is about the conditional operator |
I think this issue of letting the context type influence UP or LUB has come up recently... and I just ran into a case in internal code. It boils down to this: Future<int> f(Future<int>? f, int x) async {
return Future.value(f ?? x);
}
|
Closing: The original example is now accepted by the analyzer and the common front end with no errors. The reason why the compile-time error has been eliminated is that we are now using this algorithm when computing the type of a conditional expression ( The update is in the pipeline now, and it will be available in the beta and stable releases soon. Note that we did not add a rule whereby Instead, we're now using the context type as the resulting type if the upper bound returned by This is even more powerful than improving on the behavior of class I {}
class J {}
class A implements I, J {}
class B implements I, J {}
var b = true;
void main() => b ? A() : B(); In this case the computed upper bound is |
The Problem
Returning a value of type
FutureOr<T>
using a ternary operator where one value is of typeT
while the other is of typeFuture<T>
will result in the errorA value of type 'Object' can't be returned from the method <method-name> because it has a return type of 'FutureOr<T>'.
and can not be compiled. See the code sample below for an example.To resolve this issue the value of type
T
has to be casted asFutureOr<T>
(E.g."test" as FutureOr<String>
).Code Sample
Dart Version
The issue was reproduced in version 2.17.3
The text was updated successfully, but these errors were encountered: