Support more type arguments in generic instantiation
The real solution requires more work, so this is to buy us some time.
Change-Id: I033a77d05c0ca7658475d1fe59760ce4e5919f7e
Reviewed-on: https://dart-review.googlesource.com/65541
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index 8a39e86..4d68545 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -1115,18 +1115,39 @@
FunctionEntity get hashCodeForNativeObject =>
_findHelperFunction('hashCodeForNativeObject');
- ClassEntity get instantiation1Class => _findHelperClass('Instantiation1');
- ClassEntity get instantiation2Class => _findHelperClass('Instantiation2');
- ClassEntity get instantiation3Class => _findHelperClass('Instantiation3');
- FunctionEntity get instantiate1 => _findHelperFunction('instantiate1');
- FunctionEntity get instantiate2 => _findHelperFunction('instantiate2');
- FunctionEntity get instantiate3 => _findHelperFunction('instantiate3');
+ // TODO(johnniwinther,sra): Support arbitrary type argument count.
+ void _checkTypeArgumentCount(int typeArgumentCount) {
+ assert(typeArgumentCount > 0);
+ if (typeArgumentCount > 20) {
+ failedAt(
+ NO_LOCATION_SPANNABLE,
+ "Unsupported instantiation argument count: "
+ "${typeArgumentCount}");
+ }
+ }
+
+ ClassEntity getInstantiationClass(int typeArgumentCount) {
+ _checkTypeArgumentCount(typeArgumentCount);
+ return _findHelperClass('Instantiation$typeArgumentCount');
+ }
+
+ FunctionEntity getInstantiateFunction(int typeArgumentCount) {
+ _checkTypeArgumentCount(typeArgumentCount);
+ return _findHelperFunction('instantiate$typeArgumentCount');
+ }
+
FunctionEntity get instantiatedGenericFunctionType =>
_findHelperFunction('instantiatedGenericFunctionType');
FunctionEntity get extractFunctionTypeObjectFromInternal =>
_findHelperFunction('extractFunctionTypeObjectFromInternal');
+ bool isInstantiationClass(ClassEntity cls) {
+ return cls.library == _jsHelperLibrary &&
+ cls.name != 'Instantiation' &&
+ cls.name.startsWith('Instantiation');
+ }
+
// From dart:_internal
ClassEntity _symbolImplementationClass;
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index 361ac44..b560560 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -768,18 +768,15 @@
]);
}
- BackendImpact _genericInstantiation;
+ Map<int, BackendImpact> _genericInstantiation = <int, BackendImpact>{};
- BackendImpact get genericInstantiation =>
- _genericInstantiation ??= new BackendImpact(staticUses: [
- _commonElements.instantiate1,
- _commonElements.instantiate2,
- _commonElements.instantiate3,
+ BackendImpact getGenericInstantiation(int typeArgumentCount) =>
+ _genericInstantiation[typeArgumentCount] ??=
+ new BackendImpact(staticUses: [
+ _commonElements.getInstantiateFunction(typeArgumentCount),
_commonElements.instantiatedGenericFunctionType,
_commonElements.extractFunctionTypeObjectFromInternal,
], instantiatedClasses: [
- _commonElements.instantiation1Class,
- _commonElements.instantiation2Class,
- _commonElements.instantiation3Class,
+ _commonElements.getInstantiationClass(typeArgumentCount),
]);
}
diff --git a/pkg/compiler/lib/src/js_backend/codegen_listener.dart b/pkg/compiler/lib/src/js_backend/codegen_listener.dart
index 8332542..d276f51 100644
--- a/pkg/compiler/lib/src/js_backend/codegen_listener.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen_listener.dart
@@ -157,14 +157,8 @@
} else if (constant is InstantiationConstantValue) {
// TODO(johnniwinther): Register these using `BackendImpact`.
impactBuilder.registerTypeUse(new TypeUse.instantiation(
- _elementEnvironment
- .getThisType(_commonElements.instantiation1Class)));
- impactBuilder.registerTypeUse(new TypeUse.instantiation(
- _elementEnvironment
- .getThisType(_commonElements.instantiation2Class)));
- impactBuilder.registerTypeUse(new TypeUse.instantiation(
- _elementEnvironment
- .getThisType(_commonElements.instantiation2Class)));
+ _elementEnvironment.getThisType(_commonElements
+ .getInstantiationClass(constant.typeArguments.length))));
impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
_commonElements.instantiatedGenericFunctionType,
CallStructure.TWO_ARGS));
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index f3e8913..709b64f 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -340,24 +340,8 @@
@override
jsAst.Expression visitInstantiation(InstantiationConstantValue constant,
[_]) {
- // TODO(johnniwinther,sra): Support arbitrary type argument count.
- ClassEntity cls;
- switch (constant.typeArguments.length) {
- case 1:
- cls = _commonElements.instantiation1Class;
- break;
- case 2:
- cls = _commonElements.instantiation2Class;
- break;
- case 3:
- cls = _commonElements.instantiation3Class;
- break;
- default:
- failedAt(
- NO_LOCATION_SPANNABLE,
- "Unsupported instantiation argument count: "
- "${constant.typeArguments.length}");
- }
+ ClassEntity cls =
+ _commonElements.getInstantiationClass(constant.typeArguments.length);
List<jsAst.Expression> fields = <jsAst.Expression>[
constantReferenceGenerator(constant.function),
_reifiedTypeArguments(constant, constant.typeArguments)
diff --git a/pkg/compiler/lib/src/js_backend/impact_transformer.dart b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
index 46e3e2d4..abec762 100644
--- a/pkg/compiler/lib/src/js_backend/impact_transformer.dart
+++ b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
@@ -301,9 +301,10 @@
}
if (worldImpact.genericInstantiations.isNotEmpty) {
- registerImpact(_impacts.genericInstantiation);
for (GenericInstantiation instantiation
in worldImpact.genericInstantiations) {
+ registerImpact(_impacts
+ .getGenericInstantiation(instantiation.typeArguments.length));
_rtiNeedBuilder.registerGenericInstantiation(instantiation);
}
}
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 31545bb..7679275 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -718,9 +718,7 @@
callStubs.add(_buildStubMethod(name, function));
}
- if (cls == _commonElements.instantiation1Class ||
- cls == _commonElements.instantiation2Class ||
- cls == _commonElements.instantiation3Class) {
+ if (_commonElements.isInstantiationClass(cls)) {
callStubs.addAll(_generateInstantiationStubs(cls));
}
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 188caba..d06f62d4 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -4363,7 +4363,8 @@
}
int typeArgumentCount = node.typeArguments.length;
bool targetCanThrow = false; // TODO(sra): Is this true?
- FunctionEntity target = _instantiator(typeArgumentCount);
+ FunctionEntity target =
+ _commonElements.getInstantiateFunction(typeArgumentCount);
if (target == null) {
reporter.internalError(
_elementMap.getSpannable(targetElement, node),
@@ -4383,14 +4384,6 @@
push(instruction);
}
- FunctionEntity _instantiator(int count) {
- // TODO(johnniwinther,sra): Support arbitrary type argument count.
- if (count == 1) return _commonElements.instantiate1;
- if (count == 2) return _commonElements.instantiate2;
- if (count == 3) return _commonElements.instantiate3;
- return null;
- }
-
@override
void visitMethodInvocation(ir.MethodInvocation node) {
node.receiver.accept(this);
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 6e5d05d..1a194f5 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -3103,7 +3103,7 @@
}
/// Instantiation classes are subclasses of [Instantiation]. For now we have a
-/// few canned subclasses. Later we might generate the classes on demand.
+/// fixed number of subclasses. Later we might generate the classes on demand.
class Instantiation1<T1> extends Instantiation {
Instantiation1(Closure f) : super(f);
List get _types => [T1];
@@ -3119,16 +3119,283 @@
List get _types => [T1, T2, T3];
}
-Instantiation instantiate1<U>(Closure f) {
- return new Instantiation1<U>(f);
+class Instantiation4<T1, T2, T3, T4> extends Instantiation {
+ Instantiation4(Closure f) : super(f);
+ List get _types => [T1, T2, T3, T4];
}
-Instantiation instantiate2<U, V>(Closure f) {
- return new Instantiation2<U, V>(f);
+class Instantiation5<T1, T2, T3, T4, T5> extends Instantiation {
+ Instantiation5(Closure f) : super(f);
+ List get _types => [T1, T2, T3, T4, T5];
}
-Instantiation instantiate3<U, V, W>(Closure f) {
- return new Instantiation3<U, V, W>(f);
+class Instantiation6<T1, T2, T3, T4, T5, T6> extends Instantiation {
+ Instantiation6(Closure f) : super(f);
+ List get _types => [T1, T2, T3, T4, T5, T6];
+}
+
+class Instantiation7<T1, T2, T3, T4, T5, T6, T7> extends Instantiation {
+ Instantiation7(Closure f) : super(f);
+ List get _types => [T1, T2, T3, T4, T5, T6, T7];
+}
+
+class Instantiation8<T1, T2, T3, T4, T5, T6, T7, T8> extends Instantiation {
+ Instantiation8(Closure f) : super(f);
+ List get _types => [T1, T2, T3, T4, T5, T6, T7, T8];
+}
+
+class Instantiation9<T1, T2, T3, T4, T5, T6, T7, T8, T9> extends Instantiation {
+ Instantiation9(Closure f) : super(f);
+ List get _types => [T1, T2, T3, T4, T5, T6, T7, T8, T9];
+}
+
+class Instantiation10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>
+ extends Instantiation {
+ Instantiation10(Closure f) : super(f);
+ List get _types => [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10];
+}
+
+class Instantiation11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>
+ extends Instantiation {
+ Instantiation11(Closure f) : super(f);
+ List get _types => [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11];
+}
+
+class Instantiation12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>
+ extends Instantiation {
+ Instantiation12(Closure f) : super(f);
+ List get _types => [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12];
+}
+
+class Instantiation13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>
+ extends Instantiation {
+ Instantiation13(Closure f) : super(f);
+ List get _types => [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13];
+}
+
+class Instantiation14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14> extends Instantiation {
+ Instantiation14(Closure f) : super(f);
+ List get _types =>
+ [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14];
+}
+
+class Instantiation15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15> extends Instantiation {
+ Instantiation15(Closure f) : super(f);
+ List get _types =>
+ [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15];
+}
+
+class Instantiation16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16> extends Instantiation {
+ Instantiation16(Closure f) : super(f);
+ List get _types =>
+ [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16];
+}
+
+class Instantiation17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17> extends Instantiation {
+ Instantiation17(Closure f) : super(f);
+ List get _types => [
+ T1,
+ T2,
+ T3,
+ T4,
+ T5,
+ T6,
+ T7,
+ T8,
+ T9,
+ T10,
+ T11,
+ T12,
+ T13,
+ T14,
+ T15,
+ T16,
+ T17
+ ];
+}
+
+class Instantiation18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18> extends Instantiation {
+ Instantiation18(Closure f) : super(f);
+ List get _types => [
+ T1,
+ T2,
+ T3,
+ T4,
+ T5,
+ T6,
+ T7,
+ T8,
+ T9,
+ T10,
+ T11,
+ T12,
+ T13,
+ T14,
+ T15,
+ T16,
+ T17,
+ T18
+ ];
+}
+
+class Instantiation19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19> extends Instantiation {
+ Instantiation19(Closure f) : super(f);
+ List get _types => [
+ T1,
+ T2,
+ T3,
+ T4,
+ T5,
+ T6,
+ T7,
+ T8,
+ T9,
+ T10,
+ T11,
+ T12,
+ T13,
+ T14,
+ T15,
+ T16,
+ T17,
+ T18,
+ T19
+ ];
+}
+
+class Instantiation20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20> extends Instantiation {
+ Instantiation20(Closure f) : super(f);
+ List get _types => [
+ T1,
+ T2,
+ T3,
+ T4,
+ T5,
+ T6,
+ T7,
+ T8,
+ T9,
+ T10,
+ T11,
+ T12,
+ T13,
+ T14,
+ T15,
+ T16,
+ T17,
+ T18,
+ T19,
+ T20
+ ];
+}
+
+Instantiation instantiate1<T1>(Closure f) {
+ return new Instantiation1<T1>(f);
+}
+
+Instantiation instantiate2<T1, T2>(Closure f) {
+ return new Instantiation2<T1, T2>(f);
+}
+
+Instantiation instantiate3<T1, T2, T3>(Closure f) {
+ return new Instantiation3<T1, T2, T3>(f);
+}
+
+Instantiation instantiate4<T1, T2, T3, T4>(Closure f) {
+ return new Instantiation4<T1, T2, T3, T4>(f);
+}
+
+Instantiation instantiate5<T1, T2, T3, T4, T5>(Closure f) {
+ return new Instantiation5<T1, T2, T3, T4, T5>(f);
+}
+
+Instantiation instantiate6<T1, T2, T3, T4, T5, T6>(Closure f) {
+ return new Instantiation6<T1, T2, T3, T4, T5, T6>(f);
+}
+
+Instantiation instantiate7<T1, T2, T3, T4, T5, T6, T7>(Closure f) {
+ return new Instantiation7<T1, T2, T3, T4, T5, T6, T7>(f);
+}
+
+Instantiation instantiate8<T1, T2, T3, T4, T5, T6, T7, T8>(Closure f) {
+ return new Instantiation8<T1, T2, T3, T4, T5, T6, T7, T8>(f);
+}
+
+Instantiation instantiate9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(Closure f) {
+ return new Instantiation9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(f);
+}
+
+Instantiation instantiate10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(
+ Closure f) {
+ return new Instantiation10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(f);
+}
+
+Instantiation instantiate11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(
+ Closure f) {
+ return new Instantiation11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(f);
+}
+
+Instantiation instantiate12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(
+ Closure f) {
+ return new Instantiation12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(
+ f);
+}
+
+Instantiation
+ instantiate13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>(
+ Closure f) {
+ return new Instantiation13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13>(f);
+}
+
+Instantiation
+ instantiate14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>(
+ Closure f) {
+ return new Instantiation14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14>(f);
+}
+
+Instantiation instantiate15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15>(Closure f) {
+ return new Instantiation15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15>(f);
+}
+
+Instantiation instantiate16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16>(Closure f) {
+ return new Instantiation16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16>(f);
+}
+
+Instantiation instantiate17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17>(Closure f) {
+ return new Instantiation17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17>(f);
+}
+
+Instantiation instantiate18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18>(Closure f) {
+ return new Instantiation18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18>(f);
+}
+
+Instantiation instantiate19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19>(Closure f) {
+ return new Instantiation19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19>(f);
+}
+
+Instantiation instantiate20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20>(Closure f) {
+ return new Instantiation20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20>(f);
}
bool jsHasOwnProperty(var jsObject, String property) {
diff --git a/tests/compiler/dart2js/generic_methods/instantiation_stub_test.dart b/tests/compiler/dart2js/generic_methods/instantiation_stub_test.dart
index 4933012..ff59958 100644
--- a/tests/compiler/dart2js/generic_methods/instantiation_stub_test.dart
+++ b/tests/compiler/dart2js/generic_methods/instantiation_stub_test.dart
@@ -87,11 +87,11 @@
"Expected: $expectedStubs\n Actual: $actualStubs");
}
- checkStubs(closedWorld.commonElements.instantiation1Class,
+ checkStubs(closedWorld.commonElements.getInstantiationClass(1),
[r'call$1', r'$signature']);
- checkStubs(closedWorld.commonElements.instantiation2Class,
+ checkStubs(closedWorld.commonElements.getInstantiationClass(2),
[r'call$2', r'$signature']);
- checkStubs(closedWorld.commonElements.instantiation3Class,
+ checkStubs(closedWorld.commonElements.getInstantiationClass(3),
[r'call$3', r'call$4', r'$signature']);
});
}
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index 69f5055..fc1fe8b 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -8,6 +8,7 @@
class_test: Fail
constant_javascript_semantics4_test: Fail, OK
generic_class_is_test: Fail # Issue 32004
+many_instantiations_test/01: Crash # Issue 33819
no_such_method_test: Fail # Wrong Invocation.memberName.
statements_test: Fail
typed_locals_test: Pass, Fail
diff --git a/tests/compiler/dart2js_extra/many_instantiations_test.dart b/tests/compiler/dart2js_extra/many_instantiations_test.dart
new file mode 100644
index 0000000..9ba578a
--- /dev/null
+++ b/tests/compiler/dart2js_extra/many_instantiations_test.dart
@@ -0,0 +1,296 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test generic instantiation with many type arguments.
+
+import 'package:expect/expect.dart';
+
+f1<T1>(T1 t1) => '$t1';
+f2<T1, T2>(T1 t1, T2 t2) => '$t1$t2';
+f3<T1, T2, T3>(T1 t1, T2 t2, T3 t3) => '$t1$t2$t3';
+f4<T1, T2, T3, T4>(T1 t1, T2 t2, T3 t3, T4 t4) => '$t1$t2$t3$t4';
+f5<T1, T2, T3, T4, T5>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) => '$t1$t2$t3$t4$t5';
+f6<T1, T2, T3, T4, T5, T6>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) =>
+ '$t1$t2$t3$t4$t5$t6';
+f7<T1, T2, T3, T4, T5, T6, T7>(
+ T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) =>
+ '$t1$t2$t3$t4$t5$t6$t7';
+f8<T1, T2, T3, T4, T5, T6, T7, T8>(
+ T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) =>
+ '$t1$t2$t3$t4$t5$t6$t7$t8';
+f9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(
+ T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9) =>
+ '$t1$t2$t3$t4$t5$t6$t7$t8$t9';
+f10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5,
+ T6 t6, T7 t7, T8 t8, T9 t9, T10 t10) =>
+ '$t1$t2$t3$t4$t5$t6$t7$t8$t9$t10';
+f11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(T1 t1, T2 t2, T3 t3, T4 t4,
+ T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11) =>
+ '$t1$t2$t3$t4$t5$t6$t7$t8$t9$t10$t11';
+f12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(T1 t1, T2 t2, T3 t3,
+ T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12) =>
+ '$t1$t2$t3$t4$t5$t6$t7$t8$t9$t10$t11$t12';
+f13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>(
+ T1 t1,
+ T2 t2,
+ T3 t3,
+ T4 t4,
+ T5 t5,
+ T6 t6,
+ T7 t7,
+ T8 t8,
+ T9 t9,
+ T10 t10,
+ T11 t11,
+ T12 t12,
+ T13 t13) =>
+ '$t1$t2$t3$t4$t5$t6$t7$t8$t9$t10$t11$t12$t13';
+f14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>(
+ T1 t1,
+ T2 t2,
+ T3 t3,
+ T4 t4,
+ T5 t5,
+ T6 t6,
+ T7 t7,
+ T8 t8,
+ T9 t9,
+ T10 t10,
+ T11 t11,
+ T12 t12,
+ T13 t13,
+ T14 t14) =>
+ '$t1$t2$t3$t4$t5$t6$t7$t8$t9$t10$t11$t12$t13$t14';
+f15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>(
+ T1 t1,
+ T2 t2,
+ T3 t3,
+ T4 t4,
+ T5 t5,
+ T6 t6,
+ T7 t7,
+ T8 t8,
+ T9 t9,
+ T10 t10,
+ T11 t11,
+ T12 t12,
+ T13 t13,
+ T14 t14,
+ T15 t15) =>
+ '$t1$t2$t3$t4$t5$t6$t7$t8$t9$t10$t11$t12$t13$t14$t15';
+f16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>(
+ T1 t1,
+ T2 t2,
+ T3 t3,
+ T4 t4,
+ T5 t5,
+ T6 t6,
+ T7 t7,
+ T8 t8,
+ T9 t9,
+ T10 t10,
+ T11 t11,
+ T12 t12,
+ T13 t13,
+ T14 t14,
+ T15 t15,
+ T16 t16) =>
+ '$t1$t2$t3$t4$t5$t6$t7$t8$t9$t10$t11$t12$t13$t14$t15$t16';
+f17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17>(
+ T1 t1,
+ T2 t2,
+ T3 t3,
+ T4 t4,
+ T5 t5,
+ T6 t6,
+ T7 t7,
+ T8 t8,
+ T9 t9,
+ T10 t10,
+ T11 t11,
+ T12 t12,
+ T13 t13,
+ T14 t14,
+ T15 t15,
+ T16 t16,
+ T17 t17) =>
+ '$t1$t2$t3$t4$t5$t6$t7$t8$t9$t10$t11$t12$t13$t14$t15$t16$t17';
+f18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17,
+ T18>(
+ T1 t1,
+ T2 t2,
+ T3 t3,
+ T4 t4,
+ T5 t5,
+ T6 t6,
+ T7 t7,
+ T8 t8,
+ T9 t9,
+ T10 t10,
+ T11 t11,
+ T12 t12,
+ T13 t13,
+ T14 t14,
+ T15 t15,
+ T16 t16,
+ T17 t17,
+ T18 t18) =>
+ '$t1$t2$t3$t4$t5$t6$t7$t8$t9$t10$t11$t12$t13$t14$t15$t16$t17$t18';
+f19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17,
+ T18, T19>(
+ T1 t1,
+ T2 t2,
+ T3 t3,
+ T4 t4,
+ T5 t5,
+ T6 t6,
+ T7 t7,
+ T8 t8,
+ T9 t9,
+ T10 t10,
+ T11 t11,
+ T12 t12,
+ T13 t13,
+ T14 t14,
+ T15 t15,
+ T16 t16,
+ T17 t17,
+ T18 t18,
+ T19 t19) =>
+ '$t1$t2$t3$t4$t5$t6$t7$t8$t9$t10$t11$t12$t13$t14$t15$t16$t17$t18$t19';
+f20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17,
+ T18, T19, T20>(
+ T1 t1,
+ T2 t2,
+ T3 t3,
+ T4 t4,
+ T5 t5,
+ T6 t6,
+ T7 t7,
+ T8 t8,
+ T9 t9,
+ T10 t10,
+ T11 t11,
+ T12 t12,
+ T13 t13,
+ T14 t14,
+ T15 t15,
+ T16 t16,
+ T17 t17,
+ T18 t18,
+ T19 t19,
+ T20 t20) =>
+ '$t1$t2$t3$t4$t5$t6$t7$t8$t9$t10$t11$t12$t13$t14$t15$t16$t17$t18$t19$t20';
+f21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17,
+ T18, T19, T20, T21>(
+ T1 t1,
+ T2 t2,
+ T3 t3,
+ T4 t4,
+ T5 t5,
+ T6 t6,
+ T7 t7,
+ T8 t8,
+ T9 t9,
+ T10 t10,
+ T11 t11,
+ T12 t12,
+ T13 t13,
+ T14 t14,
+ T15 t15,
+ T16 t16,
+ T17 t17,
+ T18 t18,
+ T19 t19,
+ T20 t20,
+ T21 t21) =>
+ '$t1$t2$t3$t4$t5$t6$t7$t8$t9$t10$t11$t12$t13$t14$t15$t16$t17$t18$t19$t20$t21';
+
+m1(Function(int) f) => f(1);
+m2(Function(int, int) f) => f(1, 2);
+m3(Function(int, int, int) f) => f(1, 2, 3);
+m4(Function(int, int, int, int) f) => f(1, 2, 3, 4);
+m5(Function(int, int, int, int, int) f) => f(1, 2, 3, 4, 5);
+m6(Function(int, int, int, int, int, int) f) => f(1, 2, 3, 4, 5, 6);
+m7(Function(int, int, int, int, int, int, int) f) => f(1, 2, 3, 4, 5, 6, 7);
+m8(Function(int, int, int, int, int, int, int, int) f) =>
+ f(1, 2, 3, 4, 5, 6, 7, 8);
+m9(Function(int, int, int, int, int, int, int, int, int) f) =>
+ f(1, 2, 3, 4, 5, 6, 7, 8, 9);
+m10(Function(int, int, int, int, int, int, int, int, int, int) f) =>
+ f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+m11(Function(int, int, int, int, int, int, int, int, int, int, int) f) =>
+ f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
+m12(Function(int, int, int, int, int, int, int, int, int, int, int, int) f) =>
+ f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
+m13(
+ Function(
+ int, int, int, int, int, int, int, int, int, int, int, int, int)
+ f) =>
+ f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
+m14(
+ Function(int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int)
+ f) =>
+ f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
+m15(
+ Function(int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int)
+ f) =>
+ f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
+m16(
+ Function(int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int)
+ f) =>
+ f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
+m17(
+ Function(int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int)
+ f) =>
+ f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17);
+m18(
+ Function(int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int)
+ f) =>
+ f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18);
+m19(
+ Function(int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int)
+ f) =>
+ f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19);
+m20(
+ Function(int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int, int)
+ f) =>
+ f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20);
+m21(
+ Function(int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int, int, int, int, int)
+ f) =>
+ f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21);
+
+main() {
+ Expect.equals('1', m1(f1));
+ Expect.equals('12', m2(f2));
+ Expect.equals('123', m3(f3));
+ Expect.equals('1234', m4(f4));
+ Expect.equals('12345', m5(f5));
+ Expect.equals('123456', m6(f6));
+ Expect.equals('1234567', m7(f7));
+ Expect.equals('12345678', m8(f8));
+ Expect.equals('123456789', m9(f9));
+ Expect.equals('12345678910', m10(f10));
+ Expect.equals('1234567891011', m11(f11));
+ Expect.equals('123456789101112', m12(f12));
+ Expect.equals('12345678910111213', m13(f13));
+ Expect.equals('1234567891011121314', m14(f14));
+ Expect.equals('123456789101112131415', m15(f15));
+ Expect.equals('12345678910111213141516', m16(f16));
+ Expect.equals('1234567891011121314151617', m17(f17));
+ Expect.equals('123456789101112131415161718', m18(f18));
+ Expect.equals('12345678910111213141516171819', m19(f19));
+ Expect.equals('1234567891011121314151617181920', m20(f20));
+ Expect.equals('123456789101112131415161718192021', m21(f21)); //# 01: ok
+}