@@ -110,7 +110,6 @@ extends Comparable<X>`. This implies that current Dart constructors can
110110only allow for a declaration that resembles ` D.ofComparable ` if it uses a
111111much less precise typing, and relies on some run-time type checks.
112112
113-
114113``` dart
115114// What we can do in current Dart.
116115
@@ -157,7 +156,7 @@ The extra constraints can be helpful during inference. For instance,
157156` Map.keyToList(xs) ` above would yield a ` Map<int, List<int>> ` . In contrast:
158157
159158``` dart
160- // What we can do in current Dart doesn't work...
159+ // What we may try to do in current Dart doesn't work...
161160
162161class Map<K, V> {
163162 Map();
@@ -166,34 +165,31 @@ class Map<K, V> {
166165}
167166```
168167
169- It is possible to create a ` Map<K, List<K>> ` based on an existing
170- ` Iterable<K> ` using run-time type information. However, Dart does not in
171- general support this kind of introspection into the run-time value of type
172- arguments (and Dart does not (yet) have an 'existential open' operation),
173- so we'd almost always have to use very general types in a way which is
174- similar to the example above, which is a very substantial reduction in
175- typing precision.
176-
177- However, that won't work because it is a compile-time error to return the
178- specified map literal in the declaration of ` Map.keyToList ` . So we'd need
179- to cast it to ` Map<K, V> ` , and that's going to throw in an invocation like
180- ` Map<int, String>.keyToList(xs) ` .
181-
182- With the generic constructor, the actual type arguments like
183- ` <int, String> ` will be used as a context type for the constructor
184- invocation. The generic constructor ` Map.keyToList ` fails to infer actual
185- type arguments such that the resulting return type is a subtype of
186- ` Map<int, String> ` , and hence an invocation of the generic constructor like
187- ` Map<int, String>.keyToList(xs) ` will be a compile-time error.
188-
189- It should be noted that the type arguments of the class are inaccessible in
168+ However, that is a compile-time error because it returns a
169+ ` Map<Object?, List<Object?>> ` where the return type is ` Map<K, V> ` .
170+ But we don't know ` K ` or ` V ` , and we can't assume that ` V ` is of the form
171+ ` List<K> ` or a supertype thereof. We might try to cast the map literal to
172+ ` Map<K, V> ` , and that might work, but an invocation like
173+ ` Map<int, String>.keyToList(xs) ` will then throw at run time because the
174+ map literal isn't going to have the required type no matter which iterable
175+ we are passing as ` keys ` .
176+
177+ With the generic constructor and with an invocation like
178+ ` Map<int, String>.keyToList(xs) ` , the actual type arguments will be used as
179+ a context type for the constructor invocation. The generic constructor
180+ ` Map.keyToList ` fails to infer actual type arguments such that the
181+ resulting return type is a subtype of ` Map<int, String> ` , and hence the
182+ invocation is a compile-time error.
183+
184+ It should be noted that the type parameters of the class are inaccessible in
190185a generic constructor declaration. In that sense, the generic constructor
191186declaration is similar to a static member declaration, in that it can
192187declare and use its own formal type parameters, but it cannot access the
193188type parameters from the enclosing class.
194189
195190The similarity to generic static methods goes further. For example, we
196- could express ` keyToList ` as a static method in current Dart as follows:
191+ could express ` keyToList ` as a generic static method in current Dart as
192+ follows:
197193
198194``` dart
199195// Emulating `keyToList` as a static method in current Dart.
@@ -210,9 +206,11 @@ void main() {
210206}
211207```
212208
209+ Works perfectly!
210+
213211This illustrates that the new expressive power is not new for static
214212members (and the invocations can look exactly the same as a constructor
215- invocation in many cases).
213+ invocation in many cases), it is only new for constructors.
216214
217215However, it is still useful to generalize constructors in this way because
218216certain situations require the use of a constructor rather than a static
@@ -233,23 +231,30 @@ The grammar is adjusted as follows:
233231 | <typeIdentifier> <typeArguments> '.' <identifierOrNew>
234232 <formalParameterList>
235233
236- <factoryConstructorSignature> ::= 'const'? 'factory' <constructorSignature>
234+ <factoryConstructorSignature> ::=
235+ 'const'? 'factory' <constructorSignature>
237236
238237<redirectingFactoryConstructorSignature> ::=
239- 'const'? 'factory' <constructorSignature> '=' <constructorDesignation>
238+ 'const'? 'factory' <constructorSignature> '='
239+ <constructorDesignation>
240240
241- <constantConstructorSignature> ::= 'const' <constructorSignature>
241+ <constantConstructorSignature> ::=
242+ 'const' <constructorSignature>
242243```
243244
245+ A _ type introducing_ declaration is a class declaration, a mixin
246+ class declaration, a mixin declaration, an enum declaration, or an
247+ extension type declaration.
248+
244249A compile-time error occurs if the ` <typeIdentifier> ` in the constructor
245- signature is not the same as the name of the enclosing class, mixin or enum
250+ signature is not the same as the name of the enclosing type introducing
246251declaration, or the name of the on-declaration of the enclosing extension
247252declaration.
248253
249254### Static Analysis
250255
251- A generic constructor declaration occurs as a member of a class, mixin,
252- mixin class, enum, or extension declaration. Its current scope is the body
256+ A generic constructor declaration occurs as a member of a type introducing
257+ declaration or an extension declaration. Its current scope is the body
253258scope of the enclosing declaration. It introduces a type parameter scope
254259whose enclosing scope is the current scope of the generic constructor
255260declaration, and each type parameter declaration introduces that type
@@ -258,29 +263,29 @@ for the entire generic constructor declaration. Further scopes inside the
258263type parameter scope are created in the same way as for non-generic
259264constructors.
260265
261- * In particular , a parameter of the form ` this.p ` is in scope in the
266+ * For example , a parameter of the form ` this.p ` is in scope in the
262267initializer list, if any, and other parameters are in scope in the body, as
263268usual.*
264269
265270We establish some coherence conditions for generic constructors:
266271
267272A compile-time error occurs if any identifier in a generic constructor
268273declaration resolves to a type parameter which is declared by the enclosing
269- class, mixin, enum, or extension declaration.
274+ type introducing declaration or extension declaration.
270275
271276* In other words, a generic constructor cannot access the type parameters of
272- the class directly. In this way they are similar to static members.*
277+ a class etc. directly. In this way they are similar to static members.*
273278
274279Assume that _ D_ is a generic constructor declaration whose constructor
275280signature includes a list of actual type arguments which are applied to the
276281` <typeIdentifier> ` .
277282
278283* For example, ` C<X>.name<X extends num>() ` applies ` C ` to ` <X> ` .*
279284
280- It is a compile-time error if the enclosing class, mixin, or enum
281- declaration or the on-declaration of the enclosing extension declaration
282- does not declare any type parameters, or if it declares a different number
283- of type parameters than the number of type arguments which are passed.
285+ It is a compile-time error if the enclosing type introducing declaration,
286+ or the on-declaration of the enclosing extension declaration, does not
287+ declare any type parameters, or if it declares a different number of type
288+ parameters than the number of type arguments which are passed.
284289
285290It is a compile-time error unless these type arguments satisfy the declared
286291bounds, assuming that the bounds of the generic constructor declaration
@@ -312,7 +317,12 @@ non-generic class).
312317In this case, the super-initializer of the constructor (explicit or
313318implicit, and excepting ` Object ` that does not have a super-initializer)
314319will invoke the superconstructor with actual type arguments that correspond
315- to the type ` C<T1 .. Tk> ` of the current constructor invocation.
320+ to the type ` C<T1 .. Tk> ` of the current constructor invocation.
321+
322+ That is, if ` C ` is declared with ` k ` type parameters ` X1 .. Xk ` and
323+ superclass ` B<U1 .. Us> ` then the ` j ` th actual type argument to the super
324+ constructor invocation is obtained as ` [T1/X1 .. Tk/Xk]Uj ` , for ` j ` in
325+ ` 1 .. s ` .
316326
317327Moreover, in the body of _ D_ , the reserved word ` this ` has static type
318328` C<T1 .. Tk> ` .
@@ -360,8 +370,8 @@ whose constructor signature applies a list of actual type arguments to the
360370where ` k ` is zero, which again implies that ` C ` is a non-generic class).
361371
362372In this case, the denoted redirectee constructor is invoked with the same
363- actual type arguments. It is a compile-time error if the redirectee is a
364- generic constructor.
373+ actual type arguments, that is ` T1 .. Tk ` . It is a compile-time error if
374+ the redirectee is a generic constructor.
365375
366376* This restriction might also be relaxed in the future, if needed.*
367377
0 commit comments