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>
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index f06888f..0fc0ae8 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -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 @@
 \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 @@
 }
 
 \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 @@
 % 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 @@
 }
 
 \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}