Skip to content

Commit efdc2fa

Browse files
authored
Merge pull request #75 from dart-lang/spec_nonfun_typedef_nov18
Adding feature specification for generalized typedefs
2 parents 4f0817d + d8ec461 commit efdc2fa

File tree

1 file changed

+149
-0
lines changed

1 file changed

+149
-0
lines changed
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
# Design Document for Generalized Type Aliases 2018.
2+
3+
Author: [email protected] (@eernst).
4+
5+
Version: 0.1.
6+
7+
8+
## Motivation and Scope
9+
10+
Parameterized types in Dart can be verbose. An example is here:
11+
12+
```dart
13+
Map<ScaffoldFeatureController<SnackBar, SnackBarClosedReason>,
14+
SnackBar>
15+
```
16+
17+
Such verbose types may be needed repeatedly, and there may also be a need
18+
for several different variants of them, only differing in
19+
specific subterms. For instance, we might also need this one:
20+
21+
```dart
22+
Map<ScaffoldFeatureController<SandwichBar, SandwichBarClosedReason>,
23+
SandwichBar>
24+
```
25+
26+
This type is unlikely to work as intended if the second type argument of
27+
`Map` is changed to `SnackBar`, but such mistakes could easily happen
28+
during development. It may not even be easy to detect exactly where the
29+
mistake occurred, in cases where the erroneous type is used in some
30+
declaration, and expressions whose types depend on that declaration
31+
unexpectedly get flagged as compile-time errors, or the IDE completions
32+
in such expressions fail to list some of the expected choices.
33+
34+
This document describes how type aliases are generalized in Dart 2.2
35+
to make such verbose types more concise and consistent.
36+
37+
38+
## Feature Specification
39+
40+
The precise definition of the changes is given in the language
41+
specification, with a proposed form in
42+
[this CL](https://dart-review.googlesource.com/c/sdk/+/81414).
43+
The following sections summarize the changes.
44+
45+
46+
### Syntax
47+
48+
The grammar is modified as follows in order to support this feature:
49+
50+
```
51+
typeAlias ::=
52+
metadata 'typedef' typeAliasBody |
53+
metadata 'typedef' identifier typeParameters? '=' type ';' // CHANGED
54+
```
55+
56+
*The modification is that a type alias declaration of the form that uses
57+
`=` can define the type alias to denote any type, not just a function
58+
type.*
59+
60+
61+
### Static Analysis
62+
63+
There is no change in the treatment of existing syntax, so we describe only
64+
the treatment of syntactic forms that can be new when this feature is added.
65+
66+
The effect of a non-generic type alias declaration of the form that uses
67+
`=` with name `F` is to bind the name `F` in the library scope of the
68+
enclosing library to the type denoted by the right hand side of `=` in that
69+
declaration.
70+
71+
*This is not new, but it applies to a larger set of situations now that the
72+
right hand side can be any type. Let us call that type on the right hand
73+
side `T`. This means that `F` can be used as a type annotation, and the
74+
entity which is given type `F` is considered to have type `T`, with the
75+
same meaning as in the declaration of `F` (even if some declaration in the
76+
current library gives a new meaning to an identifier in `T`).*
77+
78+
The effect of a generic type alias declaration of the form
79+
80+
```dart
81+
typedef F<X1 extends B1 .. Xk extends Bk> = T;
82+
```
83+
84+
where metadata is omitted but may be present, is to bind the name `F` in
85+
the library scope of the enclosing library to a mapping from type argument
86+
lists to types, such that a parameterized type of the form `F<T1..Tk>` is
87+
an application of that mapping that denotes the type `[T1/X1 .. Tk/Xk]T`.
88+
89+
Let _F_ be a generic type alias of the form that uses `=` with type
90+
parameter declarations
91+
_X<sub>1</sub> extends B<sub>1</sub> .. X<sub>k</sub> extends B<sub>k</sub>_.
92+
It is a compile-time error unless satisfaction of the declared bounds
93+
_B<sub>1</sub> .. B<sub>k</sub>_ implies that the right hand side is
94+
regular-bounded, and all types that occur as subterms of the right hand
95+
side are well-bounded.
96+
Any self reference in a type alias, either directly or recursively via another
97+
type alias, is a compile-time error.
98+
99+
Let `F<T1..Tn>` be a parameterized type where `F` denotes a declaration of
100+
the form
101+
```dart
102+
typedef F<X1 extends B1 .. Xk extends Bk> = T;
103+
```
104+
where metadata is omitted but may be present. It is a compile-time error if
105+
`n != k` and it is a compile-time error if `F<T1..Tn>` is not well-bounded.
106+
107+
*These errors are not new, but they apply to a larger set of situations now
108+
that the right hand side can be any type.*
109+
110+
When a `typeName` (*that is, `identifier` or `identifier.identifier`*)
111+
that resolves to a generic type alias declaration is used as a type or
112+
evaluated as an expression, it is subject to instantiation to bound.
113+
114+
*This treatment of generic type aliases is again the same as it was
115+
previously, but it involves a larger set of types.*
116+
117+
*Note that type aliases introduce types and not classes. Consequently, a
118+
type alias can **not** be used in a position where a class is expected: in the
119+
`extends`, `with`, `implements`, or `on` clause of a class or mixin
120+
declaration; for a static member access; or in an instance creation
121+
expression (`new F()`, `const F<int>()`). On the other hand, it **can** be
122+
used as a type annotation, as a type argument, as part of a function type
123+
or function signature, as a type literal, in an `on` clause of a `try`
124+
statement, in a type test (`e is F`), and in a type cast (`e as F`).*
125+
126+
127+
### Dynamic Semantics
128+
129+
*The dynamic semantics relies on elaborations on the program performed
130+
during compilation. In particular, instantiation to bound has occurred, and
131+
hence some `typeName`s in the source code have been transformed into
132+
parameterized types, even when a type is used as an expression such that it
133+
would be a syntax error to actually add the type arguments explicitly in
134+
the source program. This means that every generic type alias receives
135+
actual type arguments at all locations where it is used. At run time it is
136+
also known that the program has no compile-time errors.*
137+
138+
For dynamic type checks, type tests, and expression evaluations, an
139+
identifier `F` resolving to a non-generic type alias and a parameterized
140+
type `F<T1..Tk>` where `F` resolves to a generic type alias are treated
141+
identically to the same type checks and type tests performed with the type
142+
denoted by that identifier or parameterized type, and the evaluation of `F`
143+
respectively `F<T1..Tk>` as an expression works the same as evaluation of a
144+
fresh type variable bound to the denoted type.
145+
146+
147+
## Versions
148+
149+
* Nov 6th, 2018, version 0.1: Initial version of this document.

0 commit comments

Comments
 (0)