Skip to content

Commit a2f40a6

Browse files
committed
Constant types; type variable elimination in constants
1 parent b9a8a62 commit a2f40a6

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
@@ -8494,8 +8494,8 @@ \subsection{Constants}
84948494
If generic function instantiation does apply to $e$
84958495
and the provided actual type arguments are \List{T}{1}{s}
84968496
then $e$ is a potentially constant and constant expression
8497-
if{}f each $T_j, j \in 1 .. s$, is a constant type expression
8498-
(\ref{constants}).
8497+
if{}f each $T_j, j \in 1 .. s$, is a constant type
8498+
(\ref{constantTypes}).
84998499
\item
85008500
An identifier expression denoting a parameter of a constant constructor
85018501
(\ref{constantConstructors})
@@ -8519,7 +8519,8 @@ \subsection{Constants}
85198519
\code{\CONST{} <$T$>[$e_1$, \ldots, $e_n$]}, or
85208520
\code{<$T$>[$e_1$, \ldots, $e_n$]}
85218521
that occurs in a constant context,
8522-
is a potentially constant expression if $T$ is a constant type expression,
8522+
is a potentially constant expression if $T$ is a constant type
8523+
(\ref{constantTypes}),
85238524
and $e_1$, \ldots{} , $e_n$ are constant expressions.
85248525
It is further a constant expression
85258526
if the list literal evaluates to an object.
@@ -8529,7 +8530,8 @@ \subsection{Constants}
85298530
\code{<$T$>\{$e_1$, \ldots, $e_n$\}}
85308531
that occurs in a constant context,
85318532
is a potentially constant expression
8532-
if $T$ is a constant type expression,
8533+
if $T$ is a constant type
8534+
(\ref{constantTypes}),
85338535
and $e_1$, \ldots{} , $e_n$ are constant expressions.
85348536
It is further a constant expression
85358537
if the list literal evaluates to an object.
@@ -8672,7 +8674,8 @@ \subsection{Constants}
86728674
\item
86738675
An expression of the form \code{$e$\,\,\AS\,\,$T$} is potentially constant
86748676
if $e$ is a potentially constant expression
8675-
and $T$ is a potentially constant type expression,
8677+
and $T$ is a potentially constant type
8678+
(\ref{constantTypes}),
86768679
and it is further constant if $e$ is constant.
86778680
\commentary{%
86788681
It is a \Error{compile-time error} to evaluate this constant expression
@@ -8682,18 +8685,57 @@ \subsection{Constants}
86828685
\item
86838686
An expression of the form \code{$e$\,\,\IS\,\,$T$} is potentially constant
86848687
if $e$ is a potentially constant expression
8685-
and $T$ is a constant type expression,
8688+
and $T$ is a constant type
8689+
(\ref{constantTypes}),
86868690
and it is further constant if $e$ is constant.
86878691
\item
86888692
An expression of the form \code{$e$\,\,is!\,\,$T$}
86898693
is equivalent to \code{!($e$\,\,is\,\,$T$)} in every way,
86908694
including whether it's potentially constant or constant.
86918695
\end{itemize}
86928696

8697+
% Being potentially constant is entirely structural, not type based,
8698+
% but the program still has to satisfy strong-mode typing.
8699+
8700+
% Constant expressions (like "const Foo(42)") always evaluate to the
8701+
% same value, with at most one value per source location.
8702+
% Potentially constant expressions that are not constant only
8703+
% allow simple operations on basic types (num, String, bool, Null). These can
8704+
% be computed statically without running user code.
8705+
86938706
\LMHash{}%
8694-
We introduce \Index{constant type expressions} and
8695-
\Index{potentially constant type expressions}
8696-
as follows:
8707+
It is a \Error{compile-time error} if an expression is required to be
8708+
a constant expression,
8709+
but its evaluation would throw an exception.
8710+
It is a \Error{compile-time error} if an assertion is evaluated as part of
8711+
a constant object expression evaluation,
8712+
and the assertion would throw an exception.
8713+
8714+
\LMHash{}%
8715+
It is a \Error{compile-time error} if the value of a constant expression
8716+
depends on itself.
8717+
8718+
\commentary{%
8719+
As an example, consider:%
8720+
}
8721+
8722+
\begin{dartCode}
8723+
\CLASS{} CircularConsts \{
8724+
// \comment{Illegal program - mutually recursive compile-time constants}
8725+
\STATIC{} \CONST{} i = j; // \comment{a compile-time constant}
8726+
\STATIC{} \CONST{} j = i; // \comment{a compile-time constant}
8727+
\}
8728+
\end{dartCode}
8729+
8730+
8731+
\subsubsection{Constant Types}
8732+
\LMLabel{constantTypes}
8733+
8734+
\LMHash{}%
8735+
A \Index{potentially constant type} respectively \Index{constant type}
8736+
is a term derived from \synt{type} which is used as a type
8737+
(\commentary{not as an expression that yields an instance of \code{Type}})
8738+
that satisfy the following criteria:
86978739
\begin{itemize}
86988740
\item
86998741
Consider a type $T$
@@ -8702,70 +8744,105 @@ \subsection{Constants}
87028744
which is not qualified by a deferred prefix,
87038745
and which is optionally followed by
87048746
type arguments of the form \code{<\List{T}{1}{r}>}.
8705-
$T$ is a potentially constant type expression
8706-
respectively a constant type expression
8707-
if{}f $T_j$ is a potentially constant respectively constant type expression
8747+
$T$ is a potentially constant type respectively a constant type
8748+
if{}f $T_j$ is a potentially constant respectively constant type
87088749
for each $j \in 1 .. r$.
87098750
\item
87108751
A type of the form \code{FutureOr<$T$>}
8711-
is a potentially constant type expression
8712-
respectively a constant type expression
8713-
if{}f $T$ is a potentially constant type expression
8714-
respectively a constant type expression.
8752+
is a potentially constant type
8753+
respectively a constant type
8754+
if{}f $T$ is a potentially constant type
8755+
respectively a constant type.
87158756
\item
87168757
%% TODO(eernst): This does not allow for type variables introduced by
8717-
%% the type itself. `Function<X>(X)` could be a constant type expression,
8758+
%% the type itself. `Function<X>(X)` could be a constant type,
87188759
%% but that is not covered by the current rules: `X` is a type variable,
8719-
%% and they are never constant type expressions.
8760+
%% and they are never constant type.
87208761
A function type
87218762
\code{$R$ Function<\metavar{typeParameters}>(\metavar{parameterTypes})}
87228763
(where $R$ and \code{<\metavar{typeParameters}>} may be omitted)
8723-
is a is a potentially constant type expression
8724-
respectively a constant type expression
8764+
is a is a potentially constant type
8765+
respectively a constant type
87258766
if $R$, \metavar{typeParameters}, and \metavar{parameterTypes}
8726-
(if present) contain only potentially constant type expressions
8727-
respectively constant type expressions.
8767+
(if present) contain only potentially constant types
8768+
respectively constant types.
87288769
\item
8729-
The type \VOID{} is a potentially constant and a constant type expression.
8770+
The type \VOID{} is a potentially constant and constant type.
87308771
\item
8731-
The type \DYNAMIC{} is a potentially constant and a constant type expression.
8772+
The type \DYNAMIC{} is a potentially constant and constant type.
87328773
\item
8733-
A type variable is a potentially constant type expression.
8774+
A type variable is a potentially constant type.
87348775
\end{itemize}
87358776

8736-
% Being potentially constant is entirely structural, not type based,
8737-
% but the program still has to satisfy strong-mode typing.
87388777

8739-
% Constant expressions (like "const Foo(42)") always evaluate to the
8740-
% same value, with at most one value per source location.
8741-
% Potentially constant expressions that are not constant only
8742-
% allow simple operations on basic types (num, String, bool, Null). These can
8743-
% be computed statically without running user code.
8778+
\subsubsection{Type Variable Elimination in Constants}
8779+
\LMLabel{typeVariableEliminationInConstants}
87448780

87458781
\LMHash{}%
8746-
It is a \Error{compile-time error} if an expression is required to be
8747-
a constant expression,
8748-
but its evaluation would throw an exception.
8749-
It is a \Error{compile-time error} if an assertion is evaluated as part of
8750-
a constant object expression evaluation,
8751-
and the assertion would throw an exception.
8782+
\BlindDefineSymbol{e, e'}%
8783+
Let $e$ be an expression that occurs in a constant context
8784+
or whose first token is \CONST,
8785+
and $e'$ be the expression yielded by type inference
8786+
(\ref{typeInference})
8787+
applied to $e$.
8788+
In this case an additional transformation is applied:
87528789

87538790
\LMHash{}%
8754-
It is a \Error{compile-time error} if the value of a constant expression
8755-
depends on itself.
8791+
Let \List{X}{1}{r} be the free type variables declared by
8792+
a class, mixin, extension, or method that contains $e$,
8793+
such that for each $j \in 1 .. r$, each $X_j$
8794+
occurs in a list of actual type arguments
8795+
which was added by type inference
8796+
(\commentary{%
8797+
so $X_j$ has one or more occurrences in $e'$,
8798+
but not all of those occurrences exist in $e$%
8799+
}).
8800+
For each $j \in 1 .. r$,
8801+
if a specific occurrence of $X_j$ in $e'$ was added by type inference,
8802+
the outermost enclosing type argument which was added by type inference
8803+
and which contains this occurrence
8804+
is replaced by its least closure with respect to \List{X}{1}{r}
8805+
(\ref{leastAndGreatestClosureOfTypes}).
87568806

87578807
\commentary{%
8758-
As an example, consider:%
8808+
Note that a free type variable which is explicitly used
8809+
as or in a type argument in a constant expression
8810+
is still a compile-time error.
8811+
For example:%
87598812
}
87608813

87618814
\begin{dartCode}
8762-
\CLASS{} CircularConsts \{
8763-
// \comment{Illegal program - mutually recursive compile-time constants}
8764-
\STATIC{} \CONST{} i = j; // \comment{a compile-time constant}
8765-
\STATIC{} \CONST{} j = i; // \comment{a compile-time constant}
8815+
\CLASS\ G<X> \{
8816+
\VOID\ foo() \{
8817+
\CONST\ List<X> c = <X>[]; // \comment{Compile-time error.}
8818+
\CONST\ List<X> d = []; // \comment{Infers \code{<X>[]}, then becomes \code{<Never>[]}.}
8819+
\}
87668820
\}
87678821
\end{dartCode}
87688822

8823+
\rationale{%
8824+
The type variable is not a constant type
8825+
(\ref{constantTypes}),
8826+
which implies that the inferred expression $e'$ is a compile-time error.
8827+
The additional transformation yields a subtype of the inferred type.
8828+
It typically replaces the type variable by \code{Never},
8829+
but it may also replace the type variable by a top type
8830+
(if the type variable occurs contravariantly),
8831+
or the type may be changed more radically
8832+
(e.g., a generic function type using $X_j$ as a type parameter bound
8833+
may be changed to \FUNCTION{} or \code{Never}).
8834+
In any case, the chosen subtype often yields
8835+
a constant which has no errors and is useful.%
8836+
}
8837+
8838+
\commentary{%
8839+
For example, \code{\CONST\,\,<Never>[]} is actually usable as
8840+
a list of any type,
8841+
and it is not a problem that every invocation of \code{add}
8842+
on this list will fail (statically or dynamically),
8843+
because that is already true for every constant list.%
8844+
}
8845+
87698846

87708847
\subsubsection{Further Remarks on Constants and Potential Constants}
87718848
\LMLabel{furtherCommentsOnConstantsAndPotentiallyConstants}
@@ -10526,8 +10603,8 @@ \subsubsection{Lists}
1052610603
if an element of a constant list literal is not constant.
1052710604
It is a \Error{compile-time error} if the type argument of a constant list literal
1052810605
(\commentary{no matter whether it is explicit or inferred})
10529-
is not a constant type expression
10530-
(\ref{constants}).
10606+
is not a constant type
10607+
(\ref{constantTypes}).
1053110608

1053210609
\rationale{%
1053310610
The binding of a formal type parameter of an enclosing class or function
@@ -11339,8 +11416,8 @@ \subsubsection{Sets}
1133911416
(\ref{equality}).
1134011417
It is a \Error{compile-time error} if the type argument of a constant set literal
1134111418
(\commentary{no matter whether it is explicit or inferred})
11342-
is not a constant type expression
11343-
(\ref{constants}).
11419+
is not a constant type
11420+
(\ref{constantTypes}).
1134411421

1134511422
\rationale{%
1134611423
The binding of a formal type parameter of an enclosing class or function
@@ -11544,8 +11621,8 @@ \subsubsection{Maps}
1154411621
(\ref{equality}).
1154511622
It is a \Error{compile-time error} if a type argument of a constant map literal
1154611623
(\commentary{no matter whether it is explicit or inferred})
11547-
is not a constant type expression
11548-
(\ref{constants}).
11624+
is not a constant type
11625+
(\ref{constantTypes}).
1154911626

1155011627
\rationale{%
1155111628
The binding of a formal type parameter of an enclosing class or function
@@ -12289,7 +12366,7 @@ \subsubsection{Const}
1228912366
\LMHash{}%
1229012367
If $T$ is a parameterized type,
1229112368
it is a
12292-
\Error{compile-time error} if $U_j$ is not a constant type expression for any
12369+
\Error{compile-time error} if $U_j$ is not a constant type for any
1229312370
$j \in 1 .. m$.
1229412371

1229512372
\begin{itemize}
@@ -24810,28 +24887,11 @@ \section{Null safety} %% !!!TODO!!!
2481024887
%% !!!At the end: Search Null, change to Never where appropriate
2481124888
%% !!!Search all `TODO`.*null
2481224889

24813-
\subsubsection{Const type variable elimination}
24814-
\LMLabel{}
24815-
24816-
If performing inference on a constant value of a generic class results in
24817-
inferred type arguments to the generic class which contain free type variables
24818-
from an enclosing generic class or method, the free type variables shall be
24819-
eliminated by taking the least closure of the inferred type with respect to the
24820-
free type variables. Note that free type variables which are explicitly used as
24821-
type arguments in constant generic instances are still considered erroneous.
24822-
24823-
\begin{dartCode}
24824-
\CLASS\ G<T> \{
24825-
\VOID\ foo() \{
24826-
\CONST\ List<T> c = <T>[]; // Error
24827-
\CONST\ List<T> d = []; // The list literal is inferred as <Never>[]
24828-
\}
24829-
\}
24830-
\end{dartCode}
24831-
2483224890
\subsubsection{Null promotion}
2483324891
\LMLabel{}
2483424892

24893+
!!!
24894+
2483524895
The machinery of type promotion is extended to promote the type of
2483624896
variables based on nullability checks subject to the same set of
2483724897
restrictions as normal promotion. The relevant checks and the types

0 commit comments

Comments
 (0)