Skip to content

Commit 0aa58cb

Browse files
committed
Type Type
1 parent bfa69af commit 0aa58cb

File tree

1 file changed

+128
-83
lines changed

1 file changed

+128
-83
lines changed

specification/dartLangSpec.tex

Lines changed: 128 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -851,10 +851,13 @@ \section{Overview}
851851
Type annotations declare the types of
852852
variables and functions (including methods and constructors).
853853
\item
854-
%% TODO(eernst): Change when integrating instantiate-to-bounds.md.
855854
Type annotations may be omitted, in which case they are generally
856-
filled in with the type \DYNAMIC{}
855+
filled in using type inference, or using the type \DYNAMIC{}
857856
(\ref{typeDynamic}).
857+
\commentary{%
858+
Type inference will be specified in a future version of this document
859+
(\ref{overview}).%
860+
}
858861
\end{enumerate}%
859862
}
860863

@@ -7693,12 +7696,7 @@ \subsection{Instantiation to Bound}
76937696
For instance, with the declaration \code{Type listType() => List;},
76947697
evaluation of the raw type expression \code{List} in the body yields
76957698
an instance of class \code{Type} reifying \code{List<dynamic>},
7696-
because \code{List} is subject to instantiation to bound.
7697-
Note that \code{List<dynamic>} is not syntactically an expression,
7698-
but it is still possible to get access to
7699-
a \code{Type} instance reifying \code{List<dynamic>}
7700-
without instantiation to bound,
7701-
because it can be the value of a type variable.%
7699+
because \code{List} is subject to instantiation to bound.%
77027700
}
77037701

77047702
\rationale{%
@@ -8413,7 +8411,9 @@ \subsection{Constants}
84138411
a mixin or a type alias that is not qualified by a deferred prefix,
84148412
is a potentially constant and constant expression.
84158413
\commentary{%
8416-
The constant expression always evaluates to a \code{Type} object.
8414+
The constant expression always evaluates to a \code{Type} object
8415+
which is a reified type
8416+
(\ref{typeType}).
84178417
For example, if $C$ is the name of a class or type alias,
84188418
the expression \code{$C$} is a constant,
84198419
and if $C$ is imported with a prefix $p$, \code{$p$.$C$} is
@@ -17435,7 +17435,8 @@ \subsection{Identifier Reference}
1743517435
\item
1743617436
If $D$ is a class, mixin, or type alias,
1743717437
the value of $e$ is an object implementing the class \code{Type}
17438-
which reifies the corresponding type.
17438+
which reifies the corresponding type
17439+
(\ref{typeType}).
1743917440
\item
1744017441
If $D$ is a type parameter $X$ then the value of $e$ is
1744117442
the value of the actual type argument corresponding to $X$
@@ -21045,41 +21046,6 @@ \subsection{Dynamic Type System}
2104521046
(\ref{actualTypes}).%
2104621047
}
2104721048

21048-
\LMHash{}%
21049-
When types are reified as instances of the built-in class \code{Type},
21050-
those objects override the \lit{==} operator
21051-
inherited from the \code{Object} class, so that
21052-
two \code{Type} objects are equal according to operator \lit{==}
21053-
if{}f the corresponding types are subtypes of each other.
21054-
21055-
\commentary{%
21056-
For example, the \code{Type} objects for the types
21057-
\DYNAMIC{} and \code{Object} are equal to each other
21058-
and hence \code{dynamic\,==\,Object} must evaluate to \TRUE.
21059-
No constraints are imposed on the built-in function \code{identical},
21060-
so \code{identical(dynamic, Object)} may be \TRUE{} or \FALSE.
21061-
21062-
Similarly, \code{Type} instances for distinct type alias declarations
21063-
declaring a name for the same function type are equal:%
21064-
}
21065-
21066-
\begin{dartCode}
21067-
\TYPEDEF{} F = \VOID{} \FUNCTION{}<X>(X);
21068-
\TYPEDEF{} G = \VOID{} \FUNCTION{}<Y>(Y);
21069-
\\
21070-
\VOID{} main() \{
21071-
assert(F == G);
21072-
\}
21073-
\end{dartCode}
21074-
21075-
\LMHash{}%
21076-
\commentary{%
21077-
Instances of \code{Type} can be obtained in various ways,
21078-
for example by using reflection,
21079-
by reading the \code{runtimeType} of an object,
21080-
or by evaluating a \emph{type literal} expression.%
21081-
}
21082-
2108321049
\LMHash{}%
2108421050
An expression is a \emph{type literal} if it is an identifier,
2108521051
or a qualified identifier,
@@ -22964,7 +22930,7 @@ \subsection{Type Never}
2296422930
}
2296522931

2296622932

22967-
\subsection{Type \code{Null}}
22933+
\subsection{Type Null}
2296822934
\LMLabel{typeNull}
2296922935

2297022936
\LMHash{}%
@@ -23010,6 +22976,109 @@ \subsection{Type \code{Null}}
2301022976
}
2301122977

2301222978

22979+
\subsection{Type Type}
22980+
\LMLabel{typeType}
22981+
22982+
\LMHash{}%
22983+
The Dart runtime supports a very limited kind of introspective reflection
22984+
for all programs
22985+
(\commentary{%
22986+
that is, without including any reflection support mechanisms,
22987+
e.g., importing \code{dart:mirrors},
22988+
or using reflection related code generation%
22989+
}).
22990+
In particular, evaluation of a type literal as an expression yields
22991+
an object whose run-time type is a subtype of the built-in type \code{Type}.
22992+
System libraries may deliver such objects as well
22993+
(\commentary{e.g., the method \code{runtimeType} on \code{Object}}).
22994+
If an object $o$ is obtained in this manner
22995+
as a reification of the Dart type $T$,
22996+
we say that $o$ is a \Index{reified type},
22997+
and we say that $o$ \IndexCustom{reifies}{type!reifies} $T$.
22998+
22999+
%% TODO(eernst): Define "same type" in one location in this spec, use it here.
23000+
\LMHash{}%
23001+
A reified type identifies the underlying Dart type in the sense that
23002+
it supports equality tests with other reified types as follows.
23003+
Let $o_1$ and $o_2$ be reified types that reify $S_1$ respectively $S_2$,
23004+
and let $o_3$ be an object which is not a reified type.
23005+
Let $U_j$ be the transitive alias expansion of $S_j$, for $j \in 1 .. 3$,
23006+
and let $v_j$ be a fresh variable whose value is $o_j$, for $j \in 1 .. 3$.
23007+
It is then guaranteed that \code{$v_1$ == $v_2$} if{}f
23008+
\NormalizedTypeOf{$U_1$} and \NormalizedTypeOf{$U_2$}
23009+
are syntactically equal,
23010+
up to equivalence of bound variables
23011+
and up to designations of the same type using different syntax
23012+
(\commentary{e.g., \code{C} and \code{prefix.C} may denote the same type}).
23013+
Conversely, \code{$v_1$ == $v_3$} will yield false.
23014+
23015+
\commentary{%
23016+
Note that we do not equate primitive top types.
23017+
For example,
23018+
reified types reifying \code{List<\VOID>} and \code{List<\DYNAMIC>}
23019+
are not equal.
23020+
However, a type variable which is declared by a function type
23021+
is treated as if it were consistently renamed to a fresh name,
23022+
thus making types identical if possible
23023+
(also known as alpha equivalence).
23024+
For example:%
23025+
}
23026+
23027+
\begin{dartCode}
23028+
\TYPEDEF{} F = \VOID{} \FUNCTION{}<X>(X);
23029+
\TYPEDEF{} G = \VOID{} \FUNCTION{}<Y>(Y);
23030+
\\
23031+
\VOID{} main() \{
23032+
print(F == G); // \comment{Prints 'true'.}
23033+
\}
23034+
\end{dartCode}
23035+
23036+
\commentary{%
23037+
Note that reified types have a primitive operator \lit{==}
23038+
(\ref{theOperatorEqualsEquals}).
23039+
This property cannot be assumed for arbitrary expressions of type \code{Type}.
23040+
For instance, we can declare
23041+
\code{\CLASS\,\,MyType\,\,\EXTENDS\,\,Type \{\ldots\}}
23042+
and override operator \lit{==}.%
23043+
}
23044+
23045+
\LMHash{}%
23046+
Let $e_1$ and $e_2$ be constant expressions
23047+
(\ref{constants})
23048+
evaluating to $o_1$ respectively $o_2$,
23049+
which are reified types reifying the Dart types $S_1$ respecively $S_2$.
23050+
Let $v_1$ and $v_2$ be fresh variables bound to $o_1$ respectively $o_2$
23051+
We then have \code{identical($v_1$, $v_2$)} if{}f
23052+
\code{$S_1$\,\,==\,\,$S_2$}.
23053+
23054+
\commentary{%
23055+
In other words, constant reified types are canonicalized.
23056+
For runtime implementations which implement identity by choosing a
23057+
canonical representative for the equivalence class of equal instances,
23058+
the choice of what type object to canonicalize to is not
23059+
observable in the language.
23060+
}
23061+
23062+
\rationale{%
23063+
As mentioned at the beginning of this section,
23064+
reified types support a very limited kind of introspective reflection.
23065+
In particular, we can compare reified types for equality,
23066+
and in the case where two reified types are equal
23067+
it is known that they reify types which are subtypes of each other
23068+
(that is, they are ``the same type'' with respect to subtyping).
23069+
But we cannot compare reified types for any inequality, that is,
23070+
we cannot determine whether one is a subtype of the other.
23071+
It is also impossible to deconstruct a reified type.
23072+
E.g., we cannot obtain the reified type for \code{$T$}
23073+
by performing operations on a given reified type for \code{List<$T$>}.
23074+
This design was chosen in order to ensure that Dart programs
23075+
do not incur the substantial implications in terms of
23076+
program size and run-time performance
23077+
that are very difficult to avoid
23078+
when a more powerful form of reflection is supported.%
23079+
}
23080+
23081+
2301323082
\subsection{Function Types}
2301423083
\LMLabel{functionTypes}
2301523084

@@ -23062,7 +23131,7 @@ \subsection{Function Types}
2306223131
}
2306323132

2306423133

23065-
\subsection{Type \FUNCTION}
23134+
\subsection{Type Function}
2306623135
\LMLabel{functionType}
2306723136

2306823137
\LMHash{}%
@@ -23103,7 +23172,7 @@ \subsection{Type \FUNCTION}
2310323172
}
2310423173

2310523174

23106-
\subsection{Type \DYNAMIC}
23175+
\subsection{Type dynamic}
2310723176
\LMLabel{typeDynamic}
2310823177

2310923178
\LMHash{}%
@@ -24233,44 +24302,20 @@ \subsubsection{Null promotion}
2423324302
These are extended as per
2423424303
[separate proposal](https://github.com/dart-lang/language/blob/master/resources/type-system/flow-analysis.md).
2423524304

24236-
\subsubsection{Runtime type equality operator}
24237-
24238-
!!!TODO!!!
24239-
24240-
Two objects $T_1$ and $T_2$ which are instances of \code{Type} (that
24241-
is, runtime type objects) are considered equal if and only if the
24242-
runtime type objects $T_1$ and $T_2$ corresponds to the types $S_1$
24243-
and $S_2$ respectively, and the normal forms \NormalizedTypeOf{$S_1$}
24244-
and \NormalizedTypeOf{$S_2$} are syntactically equal up to equivalence
24245-
of bound variables. Note that we do not equate primitive top types.
24246-
\code{List<\VOID>} and \code{List<\DYNAMIC>} are still considered
24247-
distinct runtime type objects. Note that we also do not equate
24248-
function types which differ in the placement of \REQUIRED{} on
24249-
parameter types.
24250-
24251-
\subsubsection{Constant evaluation and canonicalization}
24252-
24253-
\paragraph{Type literals}
24254-
24255-
Two constant type literals $T_1$ and $T_2$ compare as identical if they
24256-
are equal using the definition of runtime type equality specified above.
24257-
24258-
For runtime implementations which implement identity by choosing a
24259-
canonical representative for the equivalence class of equal instances,
24260-
the choice of what type object to canonicalize to is not
24261-
observable in the language.
2426224305

2426324306
\paragraph{Constant instances}
2426424307

24265-
Any two
24266-
instances which are otherwise identical except for their generic type arguments
24267-
shall be considered identical if those generic type arguments compare equal
24268-
using the definition of runtime type object equality defined above. That is,
24269-
comparison (or canonicalization) of constant instances of generic classes is
24270-
performed relative to the normal forms of their generic type arguments.
24271-
Hence, an instance of
24272-
\code{$C$<$T_0$>} compares identical to \code{C<$T_1$>} if $T_0$ and $T_1$ have the same normal form
24273-
(up to the identity of bound variables), and the objects are otherwise
24308+
!!!TODO!!!
24309+
24310+
Any two instances which are otherwise identical except for their
24311+
generic type arguments shall be considered identical if those generic
24312+
type arguments compare equal using the definition of runtime type
24313+
object equality defined above. That is, comparison (or
24314+
canonicalization) of constant instances of generic classes is
24315+
performed relative to the normal forms of their generic type
24316+
arguments. Hence, an instance of \code{$C$<$T_0$>} compares identical
24317+
to \code{C<$T_1$>} if $T_0$ and $T_1$ have the same normal form (up to
24318+
the identity of bound variables), and the objects are otherwise
2427424319
identical.
2427524320

2427624321
Implementations of the Dart runtime semantics rely on canonicalization of

0 commit comments

Comments
 (0)