From ee8256c5dd7c8ac71225a1f0ee14d6aa5e839f74 Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Mon, 17 Jul 2023 16:03:53 +0200 Subject: [PATCH 1/3] Adjust generator element type, cf. dart-lang/language#3148 --- specification/dartLangSpec.tex | 64 ++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 27 deletions(-) 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} From 92a2bb49f032b929224ddee13424ef7eec7ae797 Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Tue, 25 Jul 2023 09:43:20 +0200 Subject: [PATCH 2/3] Review response: use "type derived from", not "type of" --- specification/dartLangSpec.tex | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/specification/dartLangSpec.tex b/specification/dartLangSpec.tex index a70e76fc56..ad5dd75ba7 100644 --- a/specification/dartLangSpec.tex +++ b/specification/dartLangSpec.tex @@ -54,6 +54,8 @@ % been eliminated (it is spelled out each time which modifiers must be % present or not present). The concept is confusing now where a variable can % be late and final, and assignments to it are allowed by the static analysis. +% - Change the definition of the 'element type of a generator function', due to +% soundness issue with the current definition. % % Mar 2023 % - Clarify how line breaks are handled in a multi-line string literal. Rename @@ -2074,13 +2076,15 @@ \section{Functions} \LMHash{}% We define the -\Index{union-free type} -of a type $T$ as follows: +\Index{union-free type derived from} +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$. +then the union-free type derived from $T$ is +the union-free type derived from $S$. +Otherwise, the union-free type derived from $T$ is $T$. \commentary{% -For example, the union-free type of \code{FutureOr?} is \code{int}.% +For example, the union-free type derived from +\code{FutureOr?} is \code{int}.% } \LMHash{}% @@ -2089,7 +2093,7 @@ \section{Functions} function!generator!element type} $f$ as follows: % -Let $S$ be the union-free type of the declared return type of $f$. +Let $S$ be the union-free type derived from the declared return type of $f$. % If $f$ is a synchronous generator and $S$ implements \code{Iterable<$U$>} for some $U$ @@ -11649,7 +11653,7 @@ \subsection{Function Expressions} \LMHash{}% We say that $S$ is the -\IndexCustom{future type of a type}{type!future type of} +\IndexCustom{future type derived from a type}{type!future type derived from} $T$ in the following cases, using the first applicable case: \begin{itemize} @@ -11664,10 +11668,10 @@ \subsection{Function Expressions} \LMHash{}% When none of these cases are applicable, -we say that $T$ does not have a future type. +we say that $T$ does not derive a future type. \commentary{% -Note that if $T$ has a future type $F$ then \SubtypeNE{T}{F}, +Note that if $T$ derives a future type $F$ then \SubtypeNE{T}{F}, and $F$ is always of the form \code{$G$<...>} or \code{$G$<...>?}, where $G$ is \code{Future} or \code{FutureOr}.% } @@ -11684,17 +11688,17 @@ \subsection{Function Expressions} \item If $T$ is \code{$X$\,\&\,$S$} for some type variable $X$ and type $S$ then \begin{itemize} - \item if $S$ has future type $U$ + \item if $S$ derives future type $U$ then \DefEquals{\flatten{T}}{\code{\flatten{U}}}. \item otherwise, \DefEquals{\flatten{T}}{\code{\flatten{X}}}. \end{itemize} -\item If $T$ has future type \code{Future<$S$>} +\item If $T$ derives future type \code{Future<$S$>} or \code{FutureOr<$S$>} then \DefEquals{\flatten{T}}{S}. -\item If $T$ has future type \code{Future<$S$>?}\ or +\item If $T$ derives future type \code{Future<$S$>?}\ or \code{FutureOr<$S$>?}\ then \DefEquals{\flatten{T}}{\code{$S$?}}. \item Otherwise, \DefEquals{\flatten{T}}{T}. From aa7f8c461a4415b27b61b19acc46b630cf54b9cb Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Tue, 25 Jul 2023 09:44:16 +0200 Subject: [PATCH 3/3] Typo --- specification/dartLangSpec.tex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specification/dartLangSpec.tex b/specification/dartLangSpec.tex index ad5dd75ba7..d4a05b5423 100644 --- a/specification/dartLangSpec.tex +++ b/specification/dartLangSpec.tex @@ -11688,17 +11688,17 @@ \subsection{Function Expressions} \item If $T$ is \code{$X$\,\&\,$S$} for some type variable $X$ and type $S$ then \begin{itemize} - \item if $S$ derives future type $U$ + \item if $S$ derives a future type $U$ then \DefEquals{\flatten{T}}{\code{\flatten{U}}}. \item otherwise, \DefEquals{\flatten{T}}{\code{\flatten{X}}}. \end{itemize} -\item If $T$ derives future type \code{Future<$S$>} +\item If $T$ derives a future type \code{Future<$S$>} or \code{FutureOr<$S$>} then \DefEquals{\flatten{T}}{S}. -\item If $T$ derives future type \code{Future<$S$>?}\ or +\item If $T$ derives a future type \code{Future<$S$>?}\ or \code{FutureOr<$S$>?}\ then \DefEquals{\flatten{T}}{\code{$S$?}}. \item Otherwise, \DefEquals{\flatten{T}}{T}.