Specify dynamic type of Futures/... returned from async/... functions

Addressing https://github.com/dart-lang/sdk/issues/33213.

Change-Id: I383d496c46fa0d1bf9313f315ad767eb21577eb6
Reviewed-on: https://dart-review.googlesource.com/56487
Reviewed-by: Lasse R.H. Nielsen <lrn@google.com>
Reviewed-by: Leaf Petersen <leafp@google.com>
This commit is contained in:
Erik Ernst
2018-06-14 12:41:11 +00:00
parent 385d825469
commit 8dca855de1
+28 -3
View File
@@ -56,6 +56,8 @@
% - Introduce `subterm` and `immediate subterm`.
% - Introduce `top type`.
% - Specify configurable imports.
% - Specify the dynamic type of the Iterable/Future/Stream returned from
% invocations of functions marked sync*/async/async*.
%
% 1.15
% - Change how language specification describes control flow.
@@ -360,6 +362,14 @@ To get multiple copies of a library running simultaneously, one needs to spawn a
\subsection{Scoping}
\LMLabel{scoping}
%% TODO(eernst): Perhaps this section is the right place for the following?: We
%% need to say that `\code{Object}` and a handful of other identifiers in this document
%% are intended to refer to `the built-in class \code{Object}` etc., such that we don't
%% have to say such a thing everywhere such names are used. Currently we have about 20
%% occurrences of `the built-in class ..` and such, so they should be deleted when we
%% specify the general rule here. It needs to be said that this may be a _violation_
%% of the current scope rules, or that we assume that programs don't shadow these names.
\LMHash{}
A {\em namespace} is a mapping of names denoting declarations to actual declarations.
Let $NS$ be a namespace.
@@ -4907,7 +4917,13 @@ Completing normally or returning without a value is treated the same as returnin
}
\LMHash{}
If $f$ is marked \SYNC* (\ref{functions}), then a fresh instance $i$ implementing the built-in class \code{Iterable} is associated with the invocation and immediately returned.
If $f$ is marked \SYNC* (\ref{functions}),
then a fresh instance (\ref{generativeConstructors}) $i$
implementing \code{Iterable<$U$>} is immediately returned,
where $U$ is determined as follows:
Let $T$ be the actual return type of $f$ (\ref{actualTypeOfADeclaration}).
If $T$ is \code{Iterable<$S$>} for some type $S$, then $U$ is $S$,
otherwise $U$ is \code{Object}.
\commentary{
A Dart implementation will need to provide a specific implementation of \code{Iterable} that will be returned by \SYNC* methods.
@@ -4957,7 +4973,10 @@ Two executions of an iterator interact only via state outside the function.
% The alternative would be to cache the results of an iterator in the iterable, and check the cache at each \YIELD{}. This would have strange issues as well. The yielded value might differ from the expression in the yield. And it is a potential memory leak as the cache is kept alive by any iterator.
\LMHash{}
If $f$ is marked \ASYNC{} (\ref{functions}), then a fresh instance (\ref{generativeConstructors}) $o$ implementing the built-in class \code{Future} is associated with the invocation.
If $f$ is marked \ASYNC{} (\ref{functions}),
then a fresh instance (\ref{generativeConstructors}) $o$ is associated with the invocation,
where the dynamic type of $o$ implements \code{Future<$flatten(T)$>},
and $T$ is the actual return type of $f$ (\ref{actualTypeOfADeclaration}).
Then the body of $f$ is executed until it either suspends or completes, at which point $o$ is returned.
\commentary{
The body of $f$ may suspend during the evaluation of an \AWAIT{} expression or execution of an asynchronous \FOR{} loop.
@@ -4976,7 +4995,13 @@ so the future is not completed with an error {\em before} it has been returned.
}
\LMHash{}
If $f$ is marked \ASYNC* (\ref{functions}), then a fresh instance $s$ implementing the built-in class \code{Stream} is associated with the invocation and immediately returned.
If $f$ is marked \ASYNC* (\ref{functions}),
then a fresh instance (\ref{generativeConstructors}) $s$
implementing \code{Stream<$U$>} is immediately returned,
where $U$ is determined as follows:
Let $T$ be the actual return type of $f$ (\ref{actualTypeOfADeclaration}).
If $T$ is \code{Stream<$S$>} for some type $S$, then $U$ is $S$,
otherwise $U$ is \code{Object}.
When $s$ is listened to, execution of the body of $f$ will begin.
When execution of the body of $f$ completes:
\begin{itemize}