Description
[Edit: This issue is blocked on dart-lang/language#870; see this comment for details.]
Consider the following program:
Future<void> f() async {
throw 'f';
}
Future<void> g() async {
try {
return f();
} catch (e) {
print('Caught "$e"');
}
}
void main() async {
await g(); // Should print 'Caught "f"'.
}
Execution of this program with dart
(from 74be667, and 2.12.0-96.0.dev) gives rise to the following output:
Unhandled exception:
f
#0 f (file:///usr/local/google/home/eernst/lang/dart/scratch/202012/n011.dart:2:3)
dart-lang/sdk#57147 g (file:///usr/local/google/home/eernst/lang/dart/scratch/202012/n011.dart:7:12)
dart-lang/sdk#57148 main (file:///usr/local/google/home/eernst/lang/dart/scratch/202012/n011.dart:14:9)
dart-lang/sdk#57149 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:283:19)
dart-lang/sdk#57150 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)
However, the semantics of return f()
should have been as follows:
When
$f$ is an asynchronous non-generator with future value type$T_v$
(\ref{functions}), evaluation proceeds as follows:
($f$
is the function whose body contains the return statement)
The expression
$e$ is evaluated to an object$o$ .
(In this case, $o$
is an instance of a subtype of Future
whose type argument at Future
is void
.)
If the run-time type of
$o$ is a subtype of \code{Future<$T_v$>},
($T_v$
is the future value type of $f$
, that is, void
. And the subtype relation does hold.)
let \code{v} be a fresh variable bound to
$o$ and
evaluate \code{\AWAIT{} v} to an object$r$ ;
otherwise let$r$ be$o$ .
...
The evaluation of said await v
will throw, and hence we should proceed to execute the print
statement and return from g
by completing the body normally (and implicitly completing the returned future with the null object).
The actual behavior indicates that no such evaluation of await v
occurs, and the returned future is completed with the thrown exception, so await g()
in main
throws.
In legacy code the await occurs at the same point, with similar spec language, since commit 5af9844 of Sep 17, 2018.