Skip to content

Commit 989ffb1

Browse files
committed
Corrections from variant1 to variant2
1 parent a9a8fb8 commit 989ffb1

File tree

1 file changed

+47
-26
lines changed

1 file changed

+47
-26
lines changed

working/0723-static-extensions/feature-specification-variant2.md

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ void main() {
4949
```
5050

5151
In the case where the on-type of an extension declaration satisfies some
52-
constraints, we say that it is the _on-class_ of the extension.
52+
constraints, we say that the class/mixin/etc. which is referred in the
53+
on-type is the _on-class_ of the extension.
5354

5455
The enhancements specified for `extension` declarations in this document
5556
are only applicable to extensions that have an on-class, all other
@@ -60,7 +61,7 @@ For example:
6061

6162
```dart
6263
// Static members must ignore the type parameters. It may be useful
63-
// to omit the type parameters in the case where every member is
64+
// to omit the type parameters in the case where every member is
6465
// static.
6566
extension E2 on Map {
6667
static Map<K2, V> castFromKey<K, V, K2>(Map<K, V> source) =>
@@ -69,12 +70,14 @@ extension E2 on Map {
6970
7071
// Type parameters are used by constructors.
7172
extension E3<K extends String, V> on Map<K, V> {
72-
factory Map.fromJson(Map<String, Object?> source) => Map.from(source);
73+
factory Map.fromJson(Map<String, Object?> source) =>
74+
Map.from(source);
7375
}
7476
7577
var jsonMap = <String, Object?>{"key": 42};
7678
var typedMap = Map<String, int>.fromJson(jsonMap);
77-
// `Map<int, int>.fromJson(...)` is an error: Violates the bound of `K`.
79+
// `Map<int, int>.fromJson(...)` is an error: It violates the
80+
// bound of `K`.
7881
```
7982

8083
Another motivation for this mechanism is that it supports constructors of
@@ -152,7 +155,7 @@ of `E` is `C`, and the _constructor return type_ of `E` is `C<T1 .. Tk>`.
152155
In an extension of the form `extension E on F<T1 .. Tk> {...}` where `F` is
153156
a type alias whose transitive alias expansion denotes a class, mixin, enum,
154157
or extension type `C`, we say that the _on-class_ of `E` is `C`, and the
155-
_constructor return type_ of `E` is the transitive alias expansion of
158+
_constructor return type_ of `E` is the transitive alias expansion of
156159
`F<T1 .. Tk>`.
157160

158161
In all other cases, an extension declaration does not have an on-class nor a
@@ -271,6 +274,8 @@ or extension type resolves to an invocation of a static member of the
271274
enclosing declaration. It will never invoke a static member of an extension
272275
which is not the enclosing declaration.
273276

277+
*In other words, there is nothing new in this case.*
278+
274279
#### The instantiated constructor return type of an extension
275280

276281
Assume that _D_ is a generic extension declaration named `E` with formal
@@ -283,11 +288,27 @@ _instantiated constructor return type_ of _D_ _with actual type arguments_
283288
non-generic class `C`. In this case, the instantiated constructor return
284289
type is `C`, for any list of actual type arguments.*
285290

286-
*It is not very useful to declare a type parameter of an extension which
287-
isn't used in the on-type (and hence in the constructor return type, if it
288-
exists), because it can only be passed in an explicitly resolved
289-
invocation, e.g., `E<int>.C(42)`. In all other invocations, the value of
290-
such type variables is determined by instantiation to bound.*
291+
*Note that such type arguments can be useful, in spite of the fact that
292+
they do not occur in the type of the newly created object. For example:*
293+
294+
```dart
295+
class A {
296+
final int i;
297+
A(this.i);
298+
}
299+
300+
static extension E<X> on A {
301+
A.computed(X x, int Function(X) fun): this(fun(x));
302+
}
303+
304+
void main() {
305+
// We can create an `A` "directly".
306+
A a = A(42);
307+
308+
// We can also use a function to compute the `int`.
309+
a = A.computed('Hello!', (s) => s.length);
310+
}
311+
```
291312

292313
*As another special case, assume that _D_ has no formal type parameters,
293314
and it has a constructor return type of the form `C<S1 .. Sk>`. In this
@@ -302,7 +323,7 @@ the formal type parameters declared by an extension.
302323

303324
An _explicitly resolved invocation_ of a constructor named `C.name` in a
304325
extension declaration _D_ named `E` with `s` type parameters and on-class
305-
`C` can be expressed as `E<S1 .. Ss>.C.name(args)`,
326+
`C` can be expressed as `E<S1 .. Ss>.C.name(args)`,
306327
`E.C<U1 .. Uk>.name(args)`, or `E<S1 .. Ss>.C<U1 .. Uk>.name(args)` (and
307328
similarly for a constructor named `C` using `E<S1 .. Ss>.C(args)`, etc).
308329

@@ -342,11 +363,6 @@ If a constructor in `C` with the requested name was found, the pre-feature
342363
static analysis and dynamic semantics apply. *That is, the class always
343364
wins.*
344365

345-
Otherwise, if `m` is zero *(which means that the invocation is
346-
`C.name(args)`)*, and `C` declares a static member whose basename is the
347-
basename of `name`, the invocation is a static member invocation *(which is
348-
specified in an earlier section)*.
349-
350366
Otherwise, the invocation is partially resolved to a set _M_ of candidate
351367
constructors and static members found in extensions. Each of the candidates
352368
_kj_ is vetted as follows:
@@ -357,11 +373,16 @@ is a static member invocation *(which is specified in an earlier section)*.
357373

358374
Otherwise, assume that _kj_ is a constructor declared by an extension _D_
359375
named `E` with type parameters `X1 extends B1 .. Xs extends Bs`, on-class
360-
`C`, and on-type `C<S1 .. Sm>`. Find actual values `U1 .. Us` for
376+
`C`, and on-type `C<S1 .. Sm>`. Find actual values `U1 .. Us` for
361377
`X1 .. Xs` satisfying the bounds `B1 .. Bs`, such that
362-
`([U1/X1 .. Us/Xs]C<S1 .. Sm>) == C<T1 .. Tm>`. If this fails then remove
363-
_kj_ from the set of candidate constructors. Otherwise note that _kj_
364-
uses actual type arguments `U1 .. Us`.
378+
`([U1/X1 .. Us/Xs]C<S1 .. Sm>) == C<T1 .. Tm>`. This may determine the
379+
value of some of the actual type arguments `U1 .. Us`, and others may be
380+
unconstrained (because they do not occur in `C<T1 .. Tm>`). Actual type
381+
arguments corresponding to unconstrained type parameters are given as `_`
382+
(and they are subject to inference later on, where the types of the actual
383+
arguments `args` may influence their value). If this inference fails
384+
then remove _kj_ from the set of candidate constructors. Otherwise note
385+
that _kj_ uses actual type arguments `U1 .. Us`.
365386

366387
If all candidate constructors have been removed, or more than one candidate
367388
remains, a compile-time error occurs. Otherwise, the invocation is
@@ -371,18 +392,18 @@ constructor invocation, which is specified above.*
371392

372393
A constructor invocation of the form `C.name(args)` (respectively
373394
`C(args)`) where `C` denotes a non-generic class is resolved in the
374-
same manner, with `m == 0`. *In this case, type parameters declared by `E`
375-
will be bound to values selected by instantiation to bound.*
395+
same manner, with `m == 0`.
376396

377397
Consider a constructor invocation of the form `C.name(args)` (and similarly
378398
for `C(args)`) where `C` denotes a generic class. As usual, the
379399
invocation is treated as in the pre-feature language when it denotes a
380400
constructor declared by the class `C`.
381401

382-
In the case where the context type schema for this invocation fully
383-
determines the actual type arguments of `C`, the expression is changed to
384-
receive said actual type arguments, `C<T1 .. Tm>.name(args)`, and treated
385-
as described above.
402+
In the case where the context type schema for this invocation
403+
determines some actual type arguments of `C`, the expression is changed to
404+
receive said actual type arguments, `C<T1 .. Tm>.name(args)` (where the
405+
unconstrained actual type arguments are given as `_` and inferred later).
406+
The expression is then treated as described above.
386407

387408
Next, we construct a set _M_ containing all accessible extensions with
388409
on-class `C` that declare a constructor named `C.name` (respectively `C`).

0 commit comments

Comments
 (0)