@@ -836,10 +836,13 @@ \section{Overview}
836
836
Type annotations declare the types of
837
837
variables and functions (including methods and constructors).
838
838
\item
839
- %% TODO(eernst): Change when integrating instantiate-to-bounds.md.
840
839
Type annotations may be omitted, in which case they are generally
841
- filled in with the type \DYNAMIC{}
840
+ filled in using type inference, or using the type \DYNAMIC{}
842
841
(\ref{typeDynamic}).
842
+ \commentary{%
843
+ Type inference will be specified in a future version of this document
844
+ (\ref{overview}).%
845
+ }
843
846
\end{enumerate}%
844
847
}
845
848
@@ -3446,9 +3449,8 @@ \subsubsection{The Operator `=='}
3446
3449
which was originally obtained by evaluation of a literal symbol or
3447
3450
a constant invocation of a constructor of the \code{Symbol} class
3448
3451
has a primitive operator \lit{==}.
3449
- \item Every instance of type \code{Type}
3450
- which was originally obtained by evaluating a constant type literal
3451
- (\ref{dynamicTypeSystem})
3452
+ \item Every instance of type \code{Type} which is a reified type
3453
+ (\ref{typeType})
3452
3454
has a primitive operator \lit{==}.
3453
3455
\item An instance $o$ has a primitive operator \lit{==}
3454
3456
if the dynamic type of $o$ is a class $C$,
@@ -7654,12 +7656,7 @@ \subsection{Instantiation to Bound}
7654
7656
For instance, with the declaration \code{Type listType() => List;},
7655
7657
evaluation of the raw type expression \code{List} in the body yields
7656
7658
an instance of class \code{Type} reifying \code{List<dynamic>},
7657
- because \code{List} is subject to instantiation to bound.
7658
- Note that \code{List<dynamic>} is not syntactically an expression,
7659
- but it is still possible to get access to
7660
- a \code{Type} instance reifying \code{List<dynamic>}
7661
- without instantiation to bound,
7662
- because it can be the value of a type variable.%
7659
+ because \code{List} is subject to instantiation to bound.%
7663
7660
}
7664
7661
7665
7662
\rationale{%
@@ -8374,7 +8371,9 @@ \subsection{Constants}
8374
8371
a mixin or a type alias that is not qualified by a deferred prefix,
8375
8372
is a potentially constant and constant expression.
8376
8373
\commentary{%
8377
- The constant expression always evaluates to a \code{Type} object.
8374
+ The constant expression always evaluates to a \code{Type} object
8375
+ which is a reified type
8376
+ (\ref{typeType}).
8378
8377
For example, if $C$ is the name of a class or type alias,
8379
8378
the expression \code{$C$} is a constant,
8380
8379
and if $C$ is imported with a prefix $p$, \code{$p$.$C$} is
@@ -17327,7 +17326,8 @@ \subsection{Identifier Reference}
17327
17326
\item
17328
17327
If $D$ is a class, mixin, or type alias,
17329
17328
the value of $e$ is an object implementing the class \code{Type}
17330
- which reifies the corresponding type.
17329
+ which reifies the corresponding type
17330
+ (\ref{typeType}).
17331
17331
\item
17332
17332
If $D$ is a type parameter $X$ then the value of $e$ is
17333
17333
the value of the actual type argument corresponding to $X$
@@ -20917,41 +20917,6 @@ \subsection{Dynamic Type System}
20917
20917
(\ref{actualTypes}).%
20918
20918
}
20919
20919
20920
- \LMHash{}%
20921
- When types are reified as instances of the built-in class \code{Type},
20922
- those objects override the \lit{==} operator
20923
- inherited from the \code{Object} class, so that
20924
- two \code{Type} objects are equal according to operator \lit{==}
20925
- if{}f the corresponding types are subtypes of each other.
20926
-
20927
- \commentary{%
20928
- For example, the \code{Type} objects for the types
20929
- \DYNAMIC{} and \code{Object} are equal to each other
20930
- and hence \code{dynamic\,==\,Object} must evaluate to \TRUE.
20931
- No constraints are imposed on the built-in function \code{identical},
20932
- so \code{identical(dynamic, Object)} may be \TRUE{} or \FALSE.
20933
-
20934
- Similarly, \code{Type} instances for distinct type alias declarations
20935
- declaring a name for the same function type are equal:%
20936
- }
20937
-
20938
- \begin{dartCode}
20939
- \TYPEDEF{} F = \VOID{} \FUNCTION{}<X>(X);
20940
- \TYPEDEF{} G = \VOID{} \FUNCTION{}<Y>(Y);
20941
- \\
20942
- \VOID{} main() \{
20943
- assert(F == G);
20944
- \}
20945
- \end{dartCode}
20946
-
20947
- \LMHash{}%
20948
- \commentary{%
20949
- Instances of \code{Type} can be obtained in various ways,
20950
- for example by using reflection,
20951
- by reading the \code{runtimeType} of an object,
20952
- or by evaluating a \emph{type literal} expression.%
20953
- }
20954
-
20955
20920
\LMHash{}%
20956
20921
An expression is a \emph{type literal} if it is an identifier,
20957
20922
or a qualified identifier,
@@ -22836,7 +22801,7 @@ \subsection{Type Never}
22836
22801
}
22837
22802
22838
22803
22839
- \subsection{Type \code{ Null} }
22804
+ \subsection{Type Null}
22840
22805
\LMLabel{typeNull}
22841
22806
22842
22807
\LMHash{}%
@@ -22882,6 +22847,109 @@ \subsection{Type \code{Null}}
22882
22847
}
22883
22848
22884
22849
22850
+ \subsection{Type Type}
22851
+ \LMLabel{typeType}
22852
+
22853
+ \LMHash{}%
22854
+ The Dart runtime supports a very limited kind of introspective reflection
22855
+ for all programs
22856
+ (\commentary{%
22857
+ that is, without including any reflection support mechanisms,
22858
+ e.g., importing \code{dart:mirrors},
22859
+ or using reflection related code generation%
22860
+ }).
22861
+ In particular, evaluation of a type literal as an expression yields
22862
+ an object whose run-time type is a subtype of the built-in type \code{Type}.
22863
+ System libraries may deliver such objects as well
22864
+ (\commentary{e.g., the method \code{runtimeType} on \code{Object}}).
22865
+ If an object $o$ is obtained in this manner
22866
+ as a reification of the Dart type $T$,
22867
+ we say that $o$ is a \Index{reified type},
22868
+ and we say that $o$ \IndexCustom{reifies}{type!reifies} $T$.
22869
+
22870
+ %% TODO(eernst): Define "same type" in one location in this spec, use it here.
22871
+ \LMHash{}%
22872
+ A reified type identifies the underlying Dart type in the sense that
22873
+ it supports equality tests with other reified types as follows.
22874
+ Let $o_1$ and $o_2$ be reified types that reify $S_1$ respectively $S_2$,
22875
+ and let $o_3$ be an object which is not a reified type.
22876
+ Let $U_j$ be the transitive alias expansion of $S_j$, for $j \in 1 .. 3$,
22877
+ and let $v_j$ be a fresh variable whose value is $o_j$, for $j \in 1 .. 3$.
22878
+ It is then guaranteed that \code{$v_1$ == $v_2$} if{}f
22879
+ \NormalizedTypeOf{$U_1$} and \NormalizedTypeOf{$U_2$}
22880
+ are syntactically equal,
22881
+ up to equivalence of bound variables
22882
+ and up to designations of the same type using different syntax
22883
+ (\commentary{e.g., \code{C} and \code{prefix.C} may denote the same type}).
22884
+ Conversely, \code{$v_1$ == $v_3$} will yield false.
22885
+
22886
+ \commentary{%
22887
+ Note that we do not equate primitive top types.
22888
+ For example,
22889
+ reified types reifying \code{List<\VOID>} and \code{List<\DYNAMIC>}
22890
+ are not equal.
22891
+ However, a type variable which is declared by a function type
22892
+ is treated as if it were consistently renamed to a fresh name,
22893
+ thus making types identical if possible
22894
+ (also known as alpha equivalence).
22895
+ For example:%
22896
+ }
22897
+
22898
+ \begin{dartCode}
22899
+ \TYPEDEF{} F = \VOID{} \FUNCTION{}<X>(X);
22900
+ \TYPEDEF{} G = \VOID{} \FUNCTION{}<Y>(Y);
22901
+ \\
22902
+ \VOID{} main() \{
22903
+ print(F == G); // \comment{Prints 'true'.}
22904
+ \}
22905
+ \end{dartCode}
22906
+
22907
+ \commentary{%
22908
+ Note that reified types have a primitive operator \lit{==}
22909
+ (\ref{theOperatorEqualsEquals}).
22910
+ This property cannot be assumed for arbitrary expressions of type \code{Type}.
22911
+ For instance, we can declare
22912
+ \code{\CLASS\,\,MyType\,\,\EXTENDS\,\,Type \{\ldots\}}
22913
+ and override operator \lit{==}.%
22914
+ }
22915
+
22916
+ \LMHash{}%
22917
+ Let $e_1$ and $e_2$ be constant expressions
22918
+ (\ref{constants})
22919
+ evaluating to $o_1$ respectively $o_2$,
22920
+ which are reified types reifying the Dart types $S_1$ respecively $S_2$.
22921
+ Let $v_1$ and $v_2$ be fresh variables bound to $o_1$ respectively $o_2$
22922
+ We then have \code{identical($v_1$, $v_2$)} if{}f
22923
+ \code{$S_1$\,\,==\,\,$S_2$}.
22924
+
22925
+ \commentary{%
22926
+ In other words, constant reified types are canonicalized.
22927
+ For runtime implementations which implement identity by choosing a
22928
+ canonical representative for the equivalence class of equal instances,
22929
+ the choice of what type object to canonicalize to is not
22930
+ observable in the language.
22931
+ }
22932
+
22933
+ \rationale{%
22934
+ As mentioned at the beginning of this section,
22935
+ reified types support a very limited kind of introspective reflection.
22936
+ In particular, we can compare reified types for equality,
22937
+ and in the case where two reified types are equal
22938
+ it is known that they reify types which are subtypes of each other
22939
+ (that is, they are ``the same type'' with respect to subtyping).
22940
+ But we cannot compare reified types for any inequality, that is,
22941
+ we cannot determine whether one is a subtype of the other.
22942
+ It is also impossible to deconstruct a reified type.
22943
+ E.g., we cannot obtain the reified type for \code{$T$}
22944
+ by performing operations on a given reified type for \code{List<$T$>}.
22945
+ This design was chosen in order to ensure that Dart programs
22946
+ do not incur the substantial implications in terms of
22947
+ program size and run-time performance
22948
+ that are very difficult to avoid
22949
+ when a more powerful form of reflection is supported.%
22950
+ }
22951
+
22952
+
22885
22953
\subsection{Function Types}
22886
22954
\LMLabel{functionTypes}
22887
22955
@@ -22934,7 +23002,7 @@ \subsection{Function Types}
22934
23002
}
22935
23003
22936
23004
22937
- \subsection{Type \FUNCTION }
23005
+ \subsection{Type Function }
22938
23006
\LMLabel{functionType}
22939
23007
22940
23008
\LMHash{}%
@@ -22975,7 +23043,7 @@ \subsection{Type \FUNCTION}
22975
23043
}
22976
23044
22977
23045
22978
- \subsection{Type \DYNAMIC }
23046
+ \subsection{Type dynamic }
22979
23047
\LMLabel{typeDynamic}
22980
23048
22981
23049
\LMHash{}%
@@ -24105,44 +24173,20 @@ \subsubsection{Null promotion}
24105
24173
These are extended as per
24106
24174
[separate proposal](https://github.com/dart-lang/language/blob/master/resources/type-system/flow-analysis.md).
24107
24175
24108
- \subsubsection{Runtime type equality operator}
24109
-
24110
- !!!TODO!!!
24111
-
24112
- Two objects $T_1$ and $T_2$ which are instances of \code{Type} (that
24113
- is, runtime type objects) are considered equal if and only if the
24114
- runtime type objects $T_1$ and $T_2$ corresponds to the types $S_1$
24115
- and $S_2$ respectively, and the normal forms \NormalizedTypeOf{$S_1$}
24116
- and \NormalizedTypeOf{$S_2$} are syntactically equal up to equivalence
24117
- of bound variables. Note that we do not equate primitive top types.
24118
- \code{List<\VOID>} and \code{List<\DYNAMIC>} are still considered
24119
- distinct runtime type objects. Note that we also do not equate
24120
- function types which differ in the placement of \REQUIRED{} on
24121
- parameter types.
24122
-
24123
- \subsubsection{Constant evaluation and canonicalization}
24124
-
24125
- \paragraph{Type literals}
24126
-
24127
- Two constant type literals $T_1$ and $T_2$ compare as identical if they
24128
- are equal using the definition of runtime type equality specified above.
24129
-
24130
- For runtime implementations which implement identity by choosing a
24131
- canonical representative for the equivalence class of equal instances,
24132
- the choice of what type object to canonicalize to is not
24133
- observable in the language.
24134
24176
24135
24177
\paragraph{Constant instances}
24136
24178
24137
- Any two
24138
- instances which are otherwise identical except for their generic type arguments
24139
- shall be considered identical if those generic type arguments compare equal
24140
- using the definition of runtime type object equality defined above. That is,
24141
- comparison (or canonicalization) of constant instances of generic classes is
24142
- performed relative to the normal forms of their generic type arguments.
24143
- Hence, an instance of
24144
- \code{$C$<$T_0$>} compares identical to \code{C<$T_1$>} if $T_0$ and $T_1$ have the same normal form
24145
- (up to the identity of bound variables), and the objects are otherwise
24179
+ !!!TODO!!!
24180
+
24181
+ Any two instances which are otherwise identical except for their
24182
+ generic type arguments shall be considered identical if those generic
24183
+ type arguments compare equal using the definition of runtime type
24184
+ object equality defined above. That is, comparison (or
24185
+ canonicalization) of constant instances of generic classes is
24186
+ performed relative to the normal forms of their generic type
24187
+ arguments. Hence, an instance of \code{$C$<$T_0$>} compares identical
24188
+ to \code{C<$T_1$>} if $T_0$ and $T_1$ have the same normal form (up to
24189
+ the identity of bound variables), and the objects are otherwise
24146
24190
identical.
24147
24191
24148
24192
Implementations of the Dart runtime semantics rely on canonicalization of
0 commit comments