Skip to content

Commit 58fd148

Browse files
committed
Constant types; type variable elimination in constants
1 parent 4ec46ee commit 58fd148

File tree

1 file changed

+131
-71
lines changed

1 file changed

+131
-71
lines changed

specification/dartLangSpec.tex

Lines changed: 131 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -8647,8 +8647,8 @@ \subsection{Constants}
86478647
If generic function instantiation does apply to $e$
86488648
and the provided actual type arguments are \List{T}{1}{s}
86498649
then $e$ is a potentially constant and constant expression
8650-
if{}f each $T_j, j \in 1 .. s$, is a constant type expression
8651-
(\ref{constants}).
8650+
if{}f each $T_j, j \in 1 .. s$, is a constant type
8651+
(\ref{constantTypes}).
86528652
\item
86538653
An identifier expression denoting a parameter of a constant constructor
86548654
(\ref{constantConstructors})
@@ -8672,7 +8672,8 @@ \subsection{Constants}
86728672
\code{\CONST{} <$T$>[$e_1$, \ldots, $e_n$]}, or
86738673
\code{<$T$>[$e_1$, \ldots, $e_n$]}
86748674
that occurs in a constant context,
8675-
is a potentially constant expression if $T$ is a constant type expression,
8675+
is a potentially constant expression if $T$ is a constant type
8676+
(\ref{constantTypes}),
86768677
and $e_1$, \ldots{} , $e_n$ are constant expressions.
86778678
It is further a constant expression
86788679
if the list literal evaluates to an object.
@@ -8682,7 +8683,8 @@ \subsection{Constants}
86828683
\code{<$T$>\{$e_1$, \ldots, $e_n$\}}
86838684
that occurs in a constant context,
86848685
is a potentially constant expression
8685-
if $T$ is a constant type expression,
8686+
if $T$ is a constant type
8687+
(\ref{constantTypes}),
86868688
and $e_1$, \ldots{} , $e_n$ are constant expressions.
86878689
It is further a constant expression
86888690
if the list literal evaluates to an object.
@@ -8825,7 +8827,8 @@ \subsection{Constants}
88258827
\item
88268828
An expression of the form \code{$e$\,\,\AS\,\,$T$} is potentially constant
88278829
if $e$ is a potentially constant expression
8828-
and $T$ is a potentially constant type expression,
8830+
and $T$ is a potentially constant type
8831+
(\ref{constantTypes}),
88298832
and it is further constant if $e$ is constant.
88308833
\commentary{%
88318834
It is a \Error{compile-time error} to evaluate this constant expression
@@ -8835,18 +8838,57 @@ \subsection{Constants}
88358838
\item
88368839
An expression of the form \code{$e$\,\,\IS\,\,$T$} is potentially constant
88378840
if $e$ is a potentially constant expression
8838-
and $T$ is a constant type expression,
8841+
and $T$ is a constant type
8842+
(\ref{constantTypes}),
88398843
and it is further constant if $e$ is constant.
88408844
\item
88418845
An expression of the form \code{$e$\,\,is!\,\,$T$}
88428846
is equivalent to \code{!($e$\,\,is\,\,$T$)} in every way,
88438847
including whether it's potentially constant or constant.
88448848
\end{itemize}
88458849

8850+
% Being potentially constant is entirely structural, not type based,
8851+
% but the program still has to satisfy strong-mode typing.
8852+
8853+
% Constant expressions (like "const Foo(42)") always evaluate to the
8854+
% same value, with at most one value per source location.
8855+
% Potentially constant expressions that are not constant only
8856+
% allow simple operations on basic types (num, String, bool, Null). These can
8857+
% be computed statically without running user code.
8858+
88468859
\LMHash{}%
8847-
We introduce \Index{constant type expressions} and
8848-
\Index{potentially constant type expressions}
8849-
as follows:
8860+
It is a \Error{compile-time error} if an expression is required to be
8861+
a constant expression,
8862+
but its evaluation would throw an exception.
8863+
It is a \Error{compile-time error} if an assertion is evaluated as part of
8864+
a constant object expression evaluation,
8865+
and the assertion would throw an exception.
8866+
8867+
\LMHash{}%
8868+
It is a \Error{compile-time error} if the value of a constant expression
8869+
depends on itself.
8870+
8871+
\commentary{%
8872+
As an example, consider:%
8873+
}
8874+
8875+
\begin{dartCode}
8876+
\CLASS{} CircularConsts \{
8877+
// \comment{Illegal program - mutually recursive compile-time constants}
8878+
\STATIC{} \CONST{} i = j; // \comment{a compile-time constant}
8879+
\STATIC{} \CONST{} j = i; // \comment{a compile-time constant}
8880+
\}
8881+
\end{dartCode}
8882+
8883+
8884+
\subsubsection{Constant Types}
8885+
\LMLabel{constantTypes}
8886+
8887+
\LMHash{}%
8888+
A \Index{potentially constant type} respectively \Index{constant type}
8889+
is a term derived from \synt{type} which is used as a type
8890+
(\commentary{not as an expression that yields an instance of \code{Type}})
8891+
that satisfy the following criteria:
88508892
\begin{itemize}
88518893
\item
88528894
Consider a type $T$
@@ -8855,70 +8897,105 @@ \subsection{Constants}
88558897
which is not qualified by a deferred prefix,
88568898
and which is optionally followed by
88578899
type arguments of the form \code{<\List{T}{1}{r}>}.
8858-
$T$ is a potentially constant type expression
8859-
respectively a constant type expression
8860-
if{}f $T_j$ is a potentially constant respectively constant type expression
8900+
$T$ is a potentially constant type respectively a constant type
8901+
if{}f $T_j$ is a potentially constant respectively constant type
88618902
for each $j \in 1 .. r$.
88628903
\item
88638904
A type of the form \code{FutureOr<$T$>}
8864-
is a potentially constant type expression
8865-
respectively a constant type expression
8866-
if{}f $T$ is a potentially constant type expression
8867-
respectively a constant type expression.
8905+
is a potentially constant type
8906+
respectively a constant type
8907+
if{}f $T$ is a potentially constant type
8908+
respectively a constant type.
88688909
\item
88698910
%% TODO(eernst): This does not allow for type variables introduced by
8870-
%% the type itself. `Function<X>(X)` could be a constant type expression,
8911+
%% the type itself. `Function<X>(X)` could be a constant type,
88718912
%% but that is not covered by the current rules: `X` is a type variable,
8872-
%% and they are never constant type expressions.
8913+
%% and they are never constant type.
88738914
A function type
88748915
\code{$R$ Function<\metavar{typeParameters}>(\metavar{parameterTypes})}
88758916
(where $R$ and \code{<\metavar{typeParameters}>} may be omitted)
8876-
is a is a potentially constant type expression
8877-
respectively a constant type expression
8917+
is a is a potentially constant type
8918+
respectively a constant type
88788919
if $R$, \metavar{typeParameters}, and \metavar{parameterTypes}
8879-
(if present) contain only potentially constant type expressions
8880-
respectively constant type expressions.
8920+
(if present) contain only potentially constant types
8921+
respectively constant types.
88818922
\item
8882-
The type \VOID{} is a potentially constant and a constant type expression.
8923+
The type \VOID{} is a potentially constant and constant type.
88838924
\item
8884-
The type \DYNAMIC{} is a potentially constant and a constant type expression.
8925+
The type \DYNAMIC{} is a potentially constant and constant type.
88858926
\item
8886-
A type variable is a potentially constant type expression.
8927+
A type variable is a potentially constant type.
88878928
\end{itemize}
88888929

8889-
% Being potentially constant is entirely structural, not type based,
8890-
% but the program still has to satisfy strong-mode typing.
88918930

8892-
% Constant expressions (like "const Foo(42)") always evaluate to the
8893-
% same value, with at most one value per source location.
8894-
% Potentially constant expressions that are not constant only
8895-
% allow simple operations on basic types (num, String, bool, Null). These can
8896-
% be computed statically without running user code.
8931+
\subsubsection{Type Variable Elimination in Constants}
8932+
\LMLabel{typeVariableEliminationInConstants}
88978933

88988934
\LMHash{}%
8899-
It is a \Error{compile-time error} if an expression is required to be
8900-
a constant expression,
8901-
but its evaluation would throw an exception.
8902-
It is a \Error{compile-time error} if an assertion is evaluated as part of
8903-
a constant object expression evaluation,
8904-
and the assertion would throw an exception.
8935+
\BlindDefineSymbol{e, e'}%
8936+
Let $e$ be an expression that occurs in a constant context
8937+
or whose first token is \CONST,
8938+
and $e'$ be the expression yielded by type inference
8939+
(\ref{typeInference})
8940+
applied to $e$.
8941+
In this case an additional transformation is applied:
89058942

89068943
\LMHash{}%
8907-
It is a \Error{compile-time error} if the value of a constant expression
8908-
depends on itself.
8944+
Let \List{X}{1}{r} be the free type variables declared by
8945+
a class, mixin, extension, or method that contains $e$,
8946+
such that for each $j \in 1 .. r$, each $X_j$
8947+
occurs in a list of actual type arguments
8948+
which was added by type inference
8949+
(\commentary{%
8950+
so $X_j$ has one or more occurrences in $e'$,
8951+
but not all of those occurrences exist in $e$%
8952+
}).
8953+
For each $j \in 1 .. r$,
8954+
if a specific occurrence of $X_j$ in $e'$ was added by type inference,
8955+
the outermost enclosing type argument which was added by type inference
8956+
and which contains this occurrence
8957+
is replaced by its least closure with respect to \List{X}{1}{r}
8958+
(\ref{leastAndGreatestClosureOfTypes}).
89098959

89108960
\commentary{%
8911-
As an example, consider:%
8961+
Note that a free type variable which is explicitly used
8962+
as or in a type argument in a constant expression
8963+
is still a compile-time error.
8964+
For example:%
89128965
}
89138966

89148967
\begin{dartCode}
8915-
\CLASS{} CircularConsts \{
8916-
// \comment{Illegal program - mutually recursive compile-time constants}
8917-
\STATIC{} \CONST{} i = j; // \comment{a compile-time constant}
8918-
\STATIC{} \CONST{} j = i; // \comment{a compile-time constant}
8968+
\CLASS\ G<X> \{
8969+
\VOID\ foo() \{
8970+
\CONST\ List<X> c = <X>[]; // \comment{Compile-time error.}
8971+
\CONST\ List<X> d = []; // \comment{Infers \code{<X>[]}, then becomes \code{<Never>[]}.}
8972+
\}
89198973
\}
89208974
\end{dartCode}
89218975

8976+
\rationale{%
8977+
The type variable is not a constant type
8978+
(\ref{constantTypes}),
8979+
which implies that the inferred expression $e'$ is a compile-time error.
8980+
The additional transformation yields a subtype of the inferred type.
8981+
It typically replaces the type variable by \code{Never},
8982+
but it may also replace the type variable by a top type
8983+
(if the type variable occurs contravariantly),
8984+
or the type may be changed more radically
8985+
(e.g., a generic function type using $X_j$ as a type parameter bound
8986+
may be changed to \FUNCTION{} or \code{Never}).
8987+
In any case, the chosen subtype often yields
8988+
a constant which has no errors and is useful.%
8989+
}
8990+
8991+
\commentary{%
8992+
For example, \code{\CONST\,\,<Never>[]} is actually usable as
8993+
a list of any type,
8994+
and it is not a problem that every invocation of \code{add}
8995+
on this list will fail (statically or dynamically),
8996+
because that is already true for every constant list.%
8997+
}
8998+
89228999

89239000
\subsubsection{Further Remarks on Constants and Potential Constants}
89249001
\LMLabel{furtherCommentsOnConstantsAndPotentiallyConstants}
@@ -10679,8 +10756,8 @@ \subsubsection{Lists}
1067910756
if an element of a constant list literal is not constant.
1068010757
It is a \Error{compile-time error} if the type argument of a constant list literal
1068110758
(\commentary{no matter whether it is explicit or inferred})
10682-
is not a constant type expression
10683-
(\ref{constants}).
10759+
is not a constant type
10760+
(\ref{constantTypes}).
1068410761

1068510762
\rationale{%
1068610763
The binding of a formal type parameter of an enclosing class or function
@@ -11492,8 +11569,8 @@ \subsubsection{Sets}
1149211569
(\ref{equality}).
1149311570
It is a \Error{compile-time error} if the type argument of a constant set literal
1149411571
(\commentary{no matter whether it is explicit or inferred})
11495-
is not a constant type expression
11496-
(\ref{constants}).
11572+
is not a constant type
11573+
(\ref{constantTypes}).
1149711574

1149811575
\rationale{%
1149911576
The binding of a formal type parameter of an enclosing class or function
@@ -11697,8 +11774,8 @@ \subsubsection{Maps}
1169711774
(\ref{equality}).
1169811775
It is a \Error{compile-time error} if a type argument of a constant map literal
1169911776
(\commentary{no matter whether it is explicit or inferred})
11700-
is not a constant type expression
11701-
(\ref{constants}).
11777+
is not a constant type
11778+
(\ref{constantTypes}).
1170211779

1170311780
\rationale{%
1170411781
The binding of a formal type parameter of an enclosing class or function
@@ -12448,7 +12525,7 @@ \subsubsection{Const}
1244812525
\LMHash{}%
1244912526
If $T$ is a parameterized type,
1245012527
it is a
12451-
\Error{compile-time error} if $U_j$ is not a constant type expression for any
12528+
\Error{compile-time error} if $U_j$ is not a constant type for any
1245212529
$j \in 1 .. m$.
1245312530

1245412531
\begin{itemize}
@@ -24972,28 +25049,11 @@ \section{Null safety} %% !!!TODO!!!
2497225049
%% !!!At the end: Search Null, change to Never where appropriate
2497325050
%% !!!Search all `TODO`.*null
2497425051

24975-
\subsubsection{Const type variable elimination}
24976-
\LMLabel{}
24977-
24978-
If performing inference on a constant value of a generic class results in
24979-
inferred type arguments to the generic class which contain free type variables
24980-
from an enclosing generic class or method, the free type variables shall be
24981-
eliminated by taking the least closure of the inferred type with respect to the
24982-
free type variables. Note that free type variables which are explicitly used as
24983-
type arguments in constant generic instances are still considered erroneous.
24984-
24985-
\begin{dartCode}
24986-
\CLASS\ G<T> \{
24987-
\VOID\ foo() \{
24988-
\CONST\ List<T> c = <T>[]; // Error
24989-
\CONST\ List<T> d = []; // The list literal is inferred as <Never>[]
24990-
\}
24991-
\}
24992-
\end{dartCode}
24993-
2499425052
\subsubsection{Null promotion}
2499525053
\LMLabel{}
2499625054

25055+
!!!
25056+
2499725057
The machinery of type promotion is extended to promote the type of
2499825058
variables based on nullability checks subject to the same set of
2499925059
restrictions as normal promotion. The relevant checks and the types

0 commit comments

Comments
 (0)