-
Notifications
You must be signed in to change notification settings - Fork 1.7k
[CFE] Confusing async return semantics clarified -- no action needed #47320
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
Comments
The The That's what dart2js does (according to dartpad.dev), but the VM doesn't print Future<int> f() async {
print("4");
await null; // We're not evaluating the `throw` expression synchronously.
print("7");
throw 'f';
}
Future<Future<int>> g() async {
print("1");
await null; // We do not reach `f()` synchronously.
print("3");
var res = f();
// res.ignore(); // makes it work.
print("5: $res"); // Should be `5: Instance of 'Future<int>`
return res;
}
void main() async {
print("0");
var fut = g();
print("2: $fut"); // Should be `2: Instance of 'Future<Future<int>>`
var x = await fut; // Should just assign the `Future<int>` to `x`, but throws.
print("6: $x"); // Should be `6: Instance of 'Future<int>`
print('Done');
} This prints 1-7 in order when compiled with dart2js (with BUT, If I insert So, the VM is doing the right thing in a different order. That's at least curious, but not necessarily wrong. Even more curious, even if I set Isolate.current.setErrorsFatal(false);
var port = ReceivePort();
var eport = ReceivePort();
Isolate.current.addErrorListener(eport.sendPort);
eport.forEach((e) {
print("Reported uncaught: e[0]");
eport.close();
}).ignore();
Isolate.current.ping(port.sendPort);
await port.first; and if I drop either OK, let me do the full async analysis on the original program:
We can't guarantee the ordering of these future notifications because we don't actually promise anything, and implementations can use either sync or async completers to implement it (using a sync completer is a completely valid implementation choice when the Adding All in all, I don't think any of this is wrong except that |
Why wouldn't it still be a bug that the VM throws at
I guess the crucial point is that Even though we could say, intuitively, that the error completion has not been orphaned as long as we may await Is that really the semantics that we want? Maybe the message is that you simply never want to use |
The VM doesn't throw at
It doesn't. From the perspective of The semantics of error futures is that it's an uncaught async error if they complete with an error without having any listener. When you call And also heck yes, you never want to use You can end up with a |
@lrhn, thanks for the great analysis! I think there's no obvious improvement on the table, so I'm closing this. |
A similar topic is currently being discussed in #44395, this is different, but shares several characteristics.
Consider the following program:
The invocation
f()
should return aFuture<int>
which is completed with the thrown object and stack trace arising from thethrow
expression in the body off
. That future has a type (statically and dynamically) which is the future value type ofg
, and hence that future should be used to complete theFuture<Future<int>>
which has been returned wheng
was invoked. Inmain
, thisFuture<Future<int>>
is the value of the evaluation ofg()
, and it is awaited. The resulting object should be theFuture<int>
which was completed with an error.However, the program actually throws rather than assigning that future to
x
, indart
, whereasdart2js
correctly reaches the print statement and completes the execution ofmain
(and at that point it throws, because remaining computations are handled aftermain
terminates).I would consider this to be a bug in the VM, or in the VM specific Kernel code transformations performed by the CFE. However, I think it would be useful to double check the intended behavior in the language team first.
@lrhn, @leafpetersen, @natebosch, @jakemac53, @stereotype441, @munificent, WDYT?
The text was updated successfully, but these errors were encountered: