@@ -881,10 +881,13 @@ \section{Overview}
881
881
Type annotations declare the types of
882
882
variables and functions (including methods and constructors).
883
883
\item
884
- %% TODO(eernst): Change when integrating instantiate-to-bounds.md.
885
884
Type annotations may be omitted, in which case they are generally
886
- filled in with the type \DYNAMIC{}
885
+ filled in using type inference, or using the type \DYNAMIC{}
887
886
(\ref{typeDynamic}).
887
+ \commentary{%
888
+ Type inference will be specified in a future version of this document
889
+ (\ref{overview}).%
890
+ }
888
891
\end{enumerate}%
889
892
}
890
893
@@ -7879,12 +7882,7 @@ \subsection{Instantiation to Bound}
7879
7882
For instance, with the declaration \code{Type listType() => List;},
7880
7883
evaluation of the raw type expression \code{List} in the body yields
7881
7884
an instance of class \code{Type} reifying \code{List<dynamic>},
7882
- because \code{List} is subject to instantiation to bound.
7883
- Note that \code{List<dynamic>} is not syntactically an expression,
7884
- but it is still possible to get access to
7885
- a \code{Type} instance reifying \code{List<dynamic>}
7886
- without instantiation to bound,
7887
- because it can be the value of a type variable.%
7885
+ because \code{List} is subject to instantiation to bound.%
7888
7886
}
7889
7887
7890
7888
\rationale{%
@@ -8599,7 +8597,9 @@ \subsection{Constants}
8599
8597
a mixin or a type alias that is not qualified by a deferred prefix,
8600
8598
is a potentially constant and constant expression.
8601
8599
\commentary{%
8602
- The constant expression always evaluates to a \code{Type} object.
8600
+ The constant expression always evaluates to a \code{Type} object
8601
+ which is a reified type
8602
+ (\ref{typeType}).
8603
8603
For example, if $C$ is the name of a class or type alias,
8604
8604
the expression \code{$C$} is a constant,
8605
8605
and if $C$ is imported with a prefix $p$, \code{$p$.$C$} is
@@ -17742,7 +17742,8 @@ \subsection{Identifier Reference}
17742
17742
\item
17743
17743
If $D$ is a class, mixin, enum, or type alias,
17744
17744
the value of $e$ is an object implementing the class \code{Type}
17745
- which reifies the corresponding type.
17745
+ which reifies the corresponding type
17746
+ (\ref{typeType}).
17746
17747
\item
17747
17748
If $D$ is a type parameter $X$ then the value of $e$ is
17748
17749
the value of the actual type argument corresponding to $X$
@@ -21419,41 +21420,6 @@ \subsection{Dynamic Type System}
21419
21420
(\ref{actualTypes}).%
21420
21421
}
21421
21422
21422
- \LMHash{}%
21423
- When types are reified as instances of the built-in class \code{Type},
21424
- those objects override the \lit{==} operator
21425
- inherited from the \code{Object} class, so that
21426
- two \code{Type} objects are equal according to operator \lit{==}
21427
- if{}f the corresponding types are subtypes of each other.
21428
-
21429
- \commentary{%
21430
- For example, the \code{Type} objects for the types
21431
- \DYNAMIC{} and \code{Object} are equal to each other
21432
- and hence \code{dynamic\,==\,Object} must evaluate to \TRUE.
21433
- No constraints are imposed on the built-in function \code{identical},
21434
- so \code{identical(dynamic, Object)} may be \TRUE{} or \FALSE.
21435
-
21436
- Similarly, \code{Type} instances for distinct type alias declarations
21437
- declaring a name for the same function type are equal:%
21438
- }
21439
-
21440
- \begin{dartCode}
21441
- \TYPEDEF{} F = \VOID{} \FUNCTION{}<X>(X);
21442
- \TYPEDEF{} G = \VOID{} \FUNCTION{}<Y>(Y);
21443
- \\
21444
- \VOID{} main() \{
21445
- assert(F == G);
21446
- \}
21447
- \end{dartCode}
21448
-
21449
- \LMHash{}%
21450
- \commentary{%
21451
- Instances of \code{Type} can be obtained in various ways,
21452
- for example by using reflection,
21453
- by reading the \code{runtimeType} of an object,
21454
- or by evaluating a \emph{type literal} expression.%
21455
- }
21456
-
21457
21423
\LMHash{}%
21458
21424
An expression is a \emph{type literal} if it is an identifier,
21459
21425
or a qualified identifier,
@@ -23340,7 +23306,7 @@ \subsection{Type Never}
23340
23306
}
23341
23307
23342
23308
23343
- \subsection{Type \code{ Null} }
23309
+ \subsection{Type Null}
23344
23310
\LMLabel{typeNull}
23345
23311
23346
23312
\LMHash{}%
@@ -23386,6 +23352,109 @@ \subsection{Type \code{Null}}
23386
23352
}
23387
23353
23388
23354
23355
+ \subsection{Type Type}
23356
+ \LMLabel{typeType}
23357
+
23358
+ \LMHash{}%
23359
+ The Dart runtime supports a very limited kind of introspective reflection
23360
+ for all programs
23361
+ (\commentary{%
23362
+ that is, without including any reflection support mechanisms,
23363
+ e.g., importing \code{dart:mirrors},
23364
+ or using reflection related code generation%
23365
+ }).
23366
+ In particular, evaluation of a type literal as an expression yields
23367
+ an object whose run-time type is a subtype of the built-in type \code{Type}.
23368
+ System libraries may deliver such objects as well
23369
+ (\commentary{e.g., the method \code{runtimeType} on \code{Object}}).
23370
+ If an object $o$ is obtained in this manner
23371
+ as a reification of the Dart type $T$,
23372
+ we say that $o$ is a \Index{reified type},
23373
+ and we say that $o$ \IndexCustom{reifies}{type!reifies} $T$.
23374
+
23375
+ %% TODO(eernst): Define "same type" in one location in this spec, use it here.
23376
+ \LMHash{}%
23377
+ A reified type identifies the underlying Dart type in the sense that
23378
+ it supports equality tests with other reified types as follows.
23379
+ Let $o_1$ and $o_2$ be reified types that reify $S_1$ respectively $S_2$,
23380
+ and let $o_3$ be an object which is not a reified type.
23381
+ Let $U_j$ be the transitive alias expansion of $S_j$, for $j \in 1 .. 3$,
23382
+ and let $v_j$ be a fresh variable whose value is $o_j$, for $j \in 1 .. 3$.
23383
+ It is then guaranteed that \code{$v_1$ == $v_2$} if{}f
23384
+ \NormalizedTypeOf{$U_1$} and \NormalizedTypeOf{$U_2$}
23385
+ are syntactically equal,
23386
+ up to equivalence of bound variables
23387
+ and up to designations of the same type using different syntax
23388
+ (\commentary{e.g., \code{C} and \code{prefix.C} may denote the same type}).
23389
+ Conversely, \code{$v_1$ == $v_3$} will yield false.
23390
+
23391
+ \commentary{%
23392
+ Note that we do not equate primitive top types.
23393
+ For example,
23394
+ reified types reifying \code{List<\VOID>} and \code{List<\DYNAMIC>}
23395
+ are not equal.
23396
+ However, a type variable which is declared by a function type
23397
+ is treated as if it were consistently renamed to a fresh name,
23398
+ thus making types identical if possible
23399
+ (also known as alpha equivalence).
23400
+ For example:%
23401
+ }
23402
+
23403
+ \begin{dartCode}
23404
+ \TYPEDEF{} F = \VOID{} \FUNCTION{}<X>(X);
23405
+ \TYPEDEF{} G = \VOID{} \FUNCTION{}<Y>(Y);
23406
+ \\
23407
+ \VOID{} main() \{
23408
+ print(F == G); // \comment{Prints 'true'.}
23409
+ \}
23410
+ \end{dartCode}
23411
+
23412
+ \commentary{%
23413
+ Note that reified types have a primitive operator \lit{==}
23414
+ (\ref{theOperatorEqualsEquals}).
23415
+ This property cannot be assumed for arbitrary expressions of type \code{Type}.
23416
+ For instance, we can declare
23417
+ \code{\CLASS\,\,MyType\,\,\EXTENDS\,\,Type \{\ldots\}}
23418
+ and override operator \lit{==}.%
23419
+ }
23420
+
23421
+ \LMHash{}%
23422
+ Let $e_1$ and $e_2$ be constant expressions
23423
+ (\ref{constants})
23424
+ evaluating to $o_1$ respectively $o_2$,
23425
+ which are reified types reifying the Dart types $S_1$ respecively $S_2$.
23426
+ Let $v_1$ and $v_2$ be fresh variables bound to $o_1$ respectively $o_2$
23427
+ We then have \code{identical($v_1$, $v_2$)} if{}f
23428
+ \code{$S_1$\,\,==\,\,$S_2$}.
23429
+
23430
+ \commentary{%
23431
+ In other words, constant reified types are canonicalized.
23432
+ For runtime implementations which implement identity by choosing a
23433
+ canonical representative for the equivalence class of equal instances,
23434
+ the choice of what type object to canonicalize to is not
23435
+ observable in the language.
23436
+ }
23437
+
23438
+ \rationale{%
23439
+ As mentioned at the beginning of this section,
23440
+ reified types support a very limited kind of introspective reflection.
23441
+ In particular, we can compare reified types for equality,
23442
+ and in the case where two reified types are equal
23443
+ it is known that they reify types which are subtypes of each other
23444
+ (that is, they are ``the same type'' with respect to subtyping).
23445
+ But we cannot compare reified types for any inequality, that is,
23446
+ we cannot determine whether one is a subtype of the other.
23447
+ It is also impossible to deconstruct a reified type.
23448
+ E.g., we cannot obtain the reified type for \code{$T$}
23449
+ by performing operations on a given reified type for \code{List<$T$>}.
23450
+ This design was chosen in order to ensure that Dart programs
23451
+ do not incur the substantial implications in terms of
23452
+ program size and run-time performance
23453
+ that are very difficult to avoid
23454
+ when a more powerful form of reflection is supported.%
23455
+ }
23456
+
23457
+
23389
23458
\subsection{Function Types}
23390
23459
\LMLabel{functionTypes}
23391
23460
@@ -23438,7 +23507,7 @@ \subsection{Function Types}
23438
23507
}
23439
23508
23440
23509
23441
- \subsection{Type \FUNCTION }
23510
+ \subsection{Type Function }
23442
23511
\LMLabel{functionType}
23443
23512
23444
23513
\LMHash{}%
@@ -23479,7 +23548,7 @@ \subsection{Type \FUNCTION}
23479
23548
}
23480
23549
23481
23550
23482
- \subsection{Type \DYNAMIC }
23551
+ \subsection{Type dynamic }
23483
23552
\LMLabel{typeDynamic}
23484
23553
23485
23554
\LMHash{}%
@@ -24610,44 +24679,20 @@ \subsubsection{Null promotion}
24610
24679
These are extended as per
24611
24680
[separate proposal](https://github.com/dart-lang/language/blob/master/resources/type-system/flow-analysis.md).
24612
24681
24613
- \subsubsection{Runtime type equality operator}
24614
-
24615
- !!!TODO!!!
24616
-
24617
- Two objects $T_1$ and $T_2$ which are instances of \code{Type} (that
24618
- is, runtime type objects) are considered equal if and only if the
24619
- runtime type objects $T_1$ and $T_2$ corresponds to the types $S_1$
24620
- and $S_2$ respectively, and the normal forms \NormalizedTypeOf{$S_1$}
24621
- and \NormalizedTypeOf{$S_2$} are syntactically equal up to equivalence
24622
- of bound variables. Note that we do not equate primitive top types.
24623
- \code{List<\VOID>} and \code{List<\DYNAMIC>} are still considered
24624
- distinct runtime type objects. Note that we also do not equate
24625
- function types which differ in the placement of \REQUIRED{} on
24626
- parameter types.
24627
-
24628
- \subsubsection{Constant evaluation and canonicalization}
24629
-
24630
- \paragraph{Type literals}
24631
-
24632
- Two constant type literals $T_1$ and $T_2$ compare as identical if they
24633
- are equal using the definition of runtime type equality specified above.
24634
-
24635
- For runtime implementations which implement identity by choosing a
24636
- canonical representative for the equivalence class of equal instances,
24637
- the choice of what type object to canonicalize to is not
24638
- observable in the language.
24639
24682
24640
24683
\paragraph{Constant instances}
24641
24684
24642
- Any two
24643
- instances which are otherwise identical except for their generic type arguments
24644
- shall be considered identical if those generic type arguments compare equal
24645
- using the definition of runtime type object equality defined above. That is,
24646
- comparison (or canonicalization) of constant instances of generic classes is
24647
- performed relative to the normal forms of their generic type arguments.
24648
- Hence, an instance of
24649
- \code{$C$<$T_0$>} compares identical to \code{C<$T_1$>} if $T_0$ and $T_1$ have the same normal form
24650
- (up to the identity of bound variables), and the objects are otherwise
24685
+ !!!TODO!!!
24686
+
24687
+ Any two instances which are otherwise identical except for their
24688
+ generic type arguments shall be considered identical if those generic
24689
+ type arguments compare equal using the definition of runtime type
24690
+ object equality defined above. That is, comparison (or
24691
+ canonicalization) of constant instances of generic classes is
24692
+ performed relative to the normal forms of their generic type
24693
+ arguments. Hence, an instance of \code{$C$<$T_0$>} compares identical
24694
+ to \code{C<$T_1$>} if $T_0$ and $T_1$ have the same normal form (up to
24695
+ the identity of bound variables), and the objects are otherwise
24651
24696
identical.
24652
24697
24653
24698
Implementations of the Dart runtime semantics rely on canonicalization of
0 commit comments