diff --git a/specification/dartLangSpec.tex b/specification/dartLangSpec.tex index 9ca53a7310..a70e76fc56 100644 --- a/specification/dartLangSpec.tex +++ b/specification/dartLangSpec.tex @@ -2073,30 +2073,38 @@ \section{Functions} a function marked \code{\SYNC*} or \code{\ASYNC*} is \VOID. \LMHash{}% -We define the notion of the -\IndexCustom{element type of a generator}{function!generator!element type} -as follows: +We define the +\Index{union-free type} +of a type $T$ as follows: +If $T$ is of the form \code{$S$?}\ or the form \code{FutureOr<$S$>} +then the union-free type of $T$ is the union-free type of $S$. +Otherwise, the union-free type of $T$ is $T$. +\commentary{% +For example, the union-free type of \code{FutureOr?} is \code{int}.% +} + +\LMHash{}% +We define the +\IndexCustom{element type of a generator function}{% + function!generator!element type} +$f$ as follows: +% +Let $S$ be the union-free type of the declared return type of $f$. % -If the function $f$ is a synchronous generator -whose declared return type implements \code{Iterable<$U$>} for some $U$ +If $f$ is a synchronous generator and +$S$ implements \code{Iterable<$U$>} for some $U$ (\ref{interfaceSuperinterfaces}) then the element type of $f$ is $U$. % -If the function $f$ is an asynchronous generator -whose declared return type implements \code{Stream<$U$>} for some $U$ +If $f$ is an asynchronous generator and +$S$ implements \code{Stream<$U$>} for some $U$ then the element type of $f$ is $U$. % -Otherwise, if the function $f$ is a generator -(\commentary{synchronous or asynchronous}) +Otherwise, if $f$ is a generator (synchronous or asynchronous) +and $S$ is a supertype of \code{Object} +(\commentary{which includes \code{Object} itself}) then the element type of $f$ is \DYNAMIC. - -\commentary{% -%% TODO(eernst): Come nnbd, change `a top type' to \DYNAMIC. -In the latter case the return type is a top type, -because the declaration of $f$ would otherwise be a compile-time error. -This implies that there is no information about -the type of elements that the generator will yield.% -} +\commentary{No further cases are possible.} \subsection{Function Declarations} @@ -12463,10 +12471,10 @@ \subsection{Function Invocation} If $f$ is marked \code{\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{actualTypes}). -If $T$ is \code{Iterable<$S$>} for some type $S$, then $U$ is $S$, -otherwise $U$ is \code{Object}. +where $U$ is the actual type +(\ref{actualTypes}) +corresponding to the element type of $f$ +(\ref{functions}). \commentary{% A Dart implementation will need to provide @@ -12549,8 +12557,10 @@ \subsection{Function 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{actualTypes}). +where the dynamic type of $o$ implements \code{Future}, +where $T$ is the actual type +(\ref{actualTypes}) +corresponding to the future value type of $f$. Then the body of $f$ is executed until it either suspends or completes, at which point $o$ is returned. \commentary{% @@ -12576,10 +12586,10 @@ \subsection{Function Invocation} If $f$ is marked \code{\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{actualTypes}). -If $T$ is \code{Stream<$S$>} for some type $S$, then $U$ is $S$, -otherwise $U$ is \code{Object}. +where $U$ is the actual type +(\ref{actualTypes}) +corresponding to the element type of $f$ +(\ref{functions}). When $s$ is listened to, execution of the body of $f$ will begin. When execution of the body of $f$ completes: \begin{itemize}