Skip to content

Commit 86f7ed6

Browse files
authored
Update proposal.md
1 parent 4c0656a commit 86f7ed6

File tree

1 file changed

+52
-6
lines changed

1 file changed

+52
-6
lines changed

working/0216 - constructor tearoffs/proposal.md

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Dart Constructor Tear-offs
22

3-
Author: [email protected]<br>Version: 2.4
3+
Author: [email protected]<br>Version: 2.5
44

55
Dart allows you to tear off (aka. closurize) methods instead of just calling them. It does not allow you to tear off *constructors*, even though they are just as callable as methods (and for factory methods, the distinction is mainly philosophical).
66

@@ -171,6 +171,10 @@ Type intList = List<int>; // In-line instantiated type literal.
171171

172172
These grammar changes allows *type parameters* without following parenthesized arguments in places where we previously did not allow them. For example, this means that `<typeArguments>` becomes a *selector* by itself, not just followed by arguments.
173173

174+
It applies to instance methods as well as local, static and top-level function declarations. For instance methods, it applies to references of the form
175+
176+
`instanceMethod<int>` (with implicit `this`), `object.instanceMethod<int>` (including `this`) and `super.instanceMethod<int>`.
177+
174178
The static type of the explicitly instantiated tear-offs are the same as if the type parameter had been inferred, but no longer depends on the context type.
175179

176180
The static type of the instantiated type literal is `Type`. This also satisfies issue [#123](https://github.com/dart-lang/language/issues/123).
@@ -259,19 +263,60 @@ T top<T>(T value) => value;
259263
class C {
260264
static T stat<T>(T value) => value;
261265
T inst<T>(T value) => value;
266+
void method() {
267+
var f1 = stat<int>;
268+
var f1TypeName = stat<int>.runtimeType.toString();
269+
var f2 = inst<int>;
270+
var f2TypeName = inst<int>.runtimeType.toString();
271+
var f3 = this.inst<int>;
272+
var f3TypeName = this.inst<int>.runtimeType.toString();
273+
}
274+
}
275+
mixin M on C {
276+
static T mstat<T>(T value) => value;
277+
T minst<T>(T value) => value;
278+
void mmethod() {
279+
var f1 = mstat<int>;
280+
var f1TypeName = mstat<int>.runtimeType.toString();
281+
var f2 = minst<int>;
282+
var f2TypeName = minst<int>.runtimeType.toString();
283+
var f3 = this.minst<int>;
284+
var f3TypeName = this.minst<int>.runtimeType.toString();
285+
}
286+
}
287+
extension Ext on C {
288+
static T estat<T>(T value) => value;
289+
T einst<T>(T value) => value;
290+
void emethod() {
291+
var f1 = estat<int>; // works like (int $) => Ext.estat<int>($)
292+
var f1TypeName = estat<int>.runtimeType.toString();
293+
var f2 = einst<int>; // works like (int $) => Ext(this).einst<int>($)
294+
var f2TypeName = einst<int>.runtimeType.toString();
295+
var f3 = this.einst<int>; // works like (int $) => Ext(this).einst<int>($)
296+
var f3TypeName = this.einst<int>.runtimeType.toString();
297+
}
298+
}
299+
class D extends C with M {
300+
void method() {
301+
var f4 = super.inst<int>; // works like (int $) => super.inst<int>($)
302+
var f4TypeName = super.inst<int>.runtimeType.toString();
303+
}
262304
}
263305
void main() {
264306
// Type literals.
265307
var t1 = List<int>; // Type object for `List<int>`.
266308
var t2 = ListList<int>; // Type object for `List<List<int>>`.
267-
// Tear-offs.
309+
310+
// Instantiated function tear-offs.
268311
T local<T>(T value) => value;
269312
270313
const f1 = top<int>; // int Function(int), works like (int $) => top<int>($);
271314
const f2 = C.stat<int>; // int Function(int), works like (int $) => C.stat<int>($);
272-
var c = C();
273-
var f3 = C().inst<int>; // int Function(int), works like (int $) => c.inst<int>($);
274-
var f4 = local<int>; // int Function(int), works like (int $) => local<int>($);
315+
var f3 = local<int>; // int Function(int), works like (int $) => local<int>($);
316+
var d = D();
317+
var f4 = d.inst<int>; // int Function(int), works like (int $) => c.inst<int>($);
318+
var f5 = d.minst<int>; // int Function(int), works like (int $) => c.minst<int>($);
319+
var f6 = d.einst<int>; // int Function(int), works like (int $) => Ext(c).einst<int>($);
275320
276321
var typeName = List<int>.toString();
277322
var functionTypeName = local<int>.runtimeType.toString();
@@ -283,7 +328,7 @@ Finally, we formalize the current behavior disallowing instantiated tear-off of
283328
```dart
284329
T func<T>(T value) => value;
285330
var funcValue = func;
286-
int Function(int) f = funcValue.call; // Disallow!
331+
int Function(int) f = funcValue.call; // Disallowed!
287332
```
288333

289334
We can detect these statically, and they always throw at run-time, so we can special case them.
@@ -322,3 +367,4 @@ In this case, most of the parameters are *unnecessary*, and a tear-off expressio
322367
* 2.2: Revision. Propose generic tear-off functions.
323368
* 2.3: Include `F<Type>` as an expression, specify tear-offs from type aliases.
324369
* 2.4: Only allow tear-offs of declarations and instance methods, not arbitrary functions. Specify disambiguation strategy for parsing ambiguities.
370+
* 2.5: Elaborate on instance member tear-offs.

0 commit comments

Comments
 (0)