Version 2.14.0-339.0.dev
Merge commit '93d5c4eeeff269d798fe66df78aafc28ed3ab605' into 'dev'
diff --git a/pkg/analyzer/lib/src/generated/ffi_verifier.dart b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
index ae2d2bc7..73cc7f3 100644
--- a/pkg/analyzer/lib/src/generated/ffi_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
@@ -277,12 +277,26 @@
for (Annotation annotation in annotations) {
if (annotation.name.name == _ffiNativeName) {
+ // All FFI Natives must be static.
final isStatic = (node is FunctionDeclaration) ||
((node is MethodDeclaration) && node.isStatic);
if (!isStatic) {
_errorReporter.reportErrorForNode(
FfiCode.FFI_NATIVE_ONLY_STATIC, node);
}
+ // Leaf call FFI Natives can't use Handles.
+ ArgumentList? argumentList = annotation.arguments;
+ if (argumentList != null) {
+ NodeList<Expression> arguments = argumentList.arguments;
+ TypeArgumentList? typeArgumentList = annotation.typeArguments;
+ if (typeArgumentList != null) {
+ NodeList<TypeAnnotation> typeArguments = typeArgumentList.arguments;
+ if (typeArguments.isNotEmpty && typeArguments[0].type != null) {
+ _validateFfiLeafCallUsesNoHandles(
+ arguments, typeArguments[0].type!, node);
+ }
+ }
+ }
}
}
}
@@ -530,7 +544,8 @@
_errorReporter.reportErrorForNode(
FfiCode.MUST_BE_A_SUBTYPE, node, [TPrime, F, 'asFunction']);
}
- _validateFfiLeafCallUsesNoHandles(node, TPrime, node);
+ _validateFfiLeafCallUsesNoHandles(node.argumentList.arguments, TPrime,
+ node);
}
_validateIsLeafIsConst(node);
}
@@ -622,9 +637,8 @@
}
}
- void _validateFfiLeafCallUsesNoHandles(
- MethodInvocation node, DartType nativeType, AstNode errorNode) {
- final args = node.argumentList.arguments;
+ void _validateFfiLeafCallUsesNoHandles(NodeList<Expression> args,
+ DartType nativeType, AstNode errorNode) {
if (args.isNotEmpty) {
for (final arg in args) {
if (arg is NamedExpression) {
@@ -817,7 +831,8 @@
FfiCode.MUST_BE_A_SUBTYPE, errorNode, [S, F, 'lookupFunction']);
}
_validateIsLeafIsConst(node);
- _validateFfiLeafCallUsesNoHandles(node, S, typeArguments![0]);
+ _validateFfiLeafCallUsesNoHandles(node.argumentList.arguments, S,
+ typeArguments![0]);
}
/// Validate that none of the [annotations] are from `dart:ffi`.
diff --git a/pkg/analyzer/test/src/diagnostics/ffi_native_test.dart b/pkg/analyzer/test/src/diagnostics/ffi_native_test.dart
index e90a157..a11172c 100644
--- a/pkg/analyzer/test/src/diagnostics/ffi_native_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/ffi_native_test.dart
@@ -26,4 +26,32 @@
error(FfiCode.FFI_NATIVE_ONLY_STATIC, 31, 75),
]);
}
+
+ test_FfiNativeCanUseHandles() async {
+ await assertErrorsInCode(r'''
+import 'dart:ffi';
+@FfiNative<Handle Function(Handle)>('DoesntMatter')
+external Object doesntMatter(Object);
+''', []);
+ }
+
+ test_FfiNativeLeafMustNotReturnHandle() async {
+ await assertErrorsInCode(r'''
+import 'dart:ffi';
+@FfiNative<Handle Function()>('DoesntMatter', isLeaf:true)
+external Object doesntMatter();
+''', [
+ error(FfiCode.LEAF_CALL_MUST_NOT_RETURN_HANDLE, 19, 90),
+ ]);
+ }
+
+ test_FfiNativeLeafMustNotTakeHandles() async {
+ await assertErrorsInCode(r'''
+import 'dart:ffi';
+@FfiNative<Void Function(Handle)>('DoesntMatter', isLeaf:true)
+external void doesntMatter(Object o);
+''', [
+ error(FfiCode.LEAF_CALL_MUST_NOT_TAKE_HANDLE, 19, 100),
+ ]);
+ }
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index 010fd50..08e70bf 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -708,6 +708,12 @@
}
@override
+ TreeNode visitRedirectingFactoryTearOff(
+ RedirectingFactoryTearOff node, TreeNode? removalSentinel) {
+ return evaluateAndTransformWithContext(node, node);
+ }
+
+ @override
TreeNode visitInstantiation(Instantiation node, TreeNode? removalSentinel) {
Instantiation result =
super.visitInstantiation(node, removalSentinel) as Instantiation;
@@ -3434,7 +3440,7 @@
@override
Constant visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) {
- return defaultExpression(node);
+ return canonicalize(new RedirectingFactoryTearOffConstant(node.target));
}
@override
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index e49f3a2e..8842a74 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -3178,8 +3178,13 @@
tearOffExpression = _helper.forest
.createConstructorTearOff(token.charOffset, tearOff);
} else if (tearOff is Procedure) {
- tearOffExpression =
- _helper.forest.createStaticTearOff(token.charOffset, tearOff);
+ if (tearOff.isRedirectingFactory) {
+ tearOffExpression = _helper.forest
+ .createRedirectingFactoryTearOff(token.charOffset, tearOff);
+ } else {
+ tearOffExpression = _helper.forest
+ .createStaticTearOff(token.charOffset, tearOff);
+ }
} else if (tearOff != null) {
unhandled("${tearOff.runtimeType}", "buildPropertyAccess",
operatorOffset, _helper.uri);
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index 19e7096..8ba13f0 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -836,9 +836,17 @@
StaticTearOff createStaticTearOff(int fileOffset, Procedure procedure) {
// ignore: unnecessary_null_comparison
assert(fileOffset != null);
+ assert(!procedure.isRedirectingFactory);
return new StaticTearOff(procedure)..fileOffset = fileOffset;
}
+ RedirectingFactoryTearOff createRedirectingFactoryTearOff(
+ int fileOffset, Procedure procedure) {
+ // ignore: unnecessary_null_comparison
+ assert(fileOffset != null);
+ return new RedirectingFactoryTearOff(procedure)..fileOffset = fileOffset;
+ }
+
Instantiation createInstantiation(
int fileOffset, Expression expression, List<DartType> typeArguments) {
// ignore: unnecessary_null_comparison
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index a435c3d..9e9b67d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -225,7 +225,9 @@
@override
ExpressionInferenceResult visitRedirectingFactoryTearOff(
RedirectingFactoryTearOff node, DartType typeContext) {
- return _unhandledExpression(node, typeContext);
+ DartType type =
+ node.target.function.computeFunctionType(inferrer.library.nonNullable);
+ return inferrer.instantiateTearOff(type, typeContext, node);
}
@override
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.expect
index 4251833..b0293c7 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.expect
@@ -62,7 +62,7 @@
return self::test();
constants {
- #C1 = static-tearoff self::A::redirectingFactory
- #C2 = static-tearoff self::A::redirectingFactoryChild
- #C3 = static-tearoff self::A::redirectingTwice
+ #C1 = redirecting-factory-tearoff self::A::redirectingFactory
+ #C2 = redirecting-factory-tearoff self::A::redirectingFactoryChild
+ #C3 = redirecting-factory-tearoff self::A::redirectingTwice
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.transformed.expect
index 4f2b568..44e6acc 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.transformed.expect
@@ -62,7 +62,7 @@
return self::test();
constants {
- #C1 = static-tearoff self::A::redirectingFactory
- #C2 = static-tearoff self::A::redirectingFactoryChild
- #C3 = static-tearoff self::A::redirectingTwice
+ #C1 = redirecting-factory-tearoff self::A::redirectingFactory
+ #C2 = redirecting-factory-tearoff self::A::redirectingFactoryChild
+ #C3 = redirecting-factory-tearoff self::A::redirectingTwice
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.expect
index 4251833..b0293c7 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.expect
@@ -62,7 +62,7 @@
return self::test();
constants {
- #C1 = static-tearoff self::A::redirectingFactory
- #C2 = static-tearoff self::A::redirectingFactoryChild
- #C3 = static-tearoff self::A::redirectingTwice
+ #C1 = redirecting-factory-tearoff self::A::redirectingFactory
+ #C2 = redirecting-factory-tearoff self::A::redirectingFactoryChild
+ #C3 = redirecting-factory-tearoff self::A::redirectingTwice
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.transformed.expect
index 4f2b568..44e6acc 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.transformed.expect
@@ -62,7 +62,7 @@
return self::test();
constants {
- #C1 = static-tearoff self::A::redirectingFactory
- #C2 = static-tearoff self::A::redirectingFactoryChild
- #C3 = static-tearoff self::A::redirectingTwice
+ #C1 = redirecting-factory-tearoff self::A::redirectingFactory
+ #C2 = redirecting-factory-tearoff self::A::redirectingFactoryChild
+ #C3 = redirecting-factory-tearoff self::A::redirectingTwice
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart
new file mode 100644
index 0000000..75d63fa
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart
@@ -0,0 +1,163 @@
+// Copyright (c) 2021, 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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+main() {
+ print('inSoundMode: $inSoundMode');
+ testNoArgs();
+ testArgs();
+}
+
+class Class1 {
+ Class1._();
+ factory Class1() = Class1._;
+}
+
+class Class2 {
+ Class2._();
+ factory Class2.named() = Class2._;
+}
+
+testNoArgs() {
+ var f1a = Class1.new;
+ var c1a = f1a();
+ expect(true, c1a is Class1);
+
+ dynamic f1b = Class1.new;
+ var c1b = f1b();
+ expect(true, c1b is Class1);
+
+ expect(true, identical(f1a, f1b));
+
+ var f2a = Class2.named;
+ var c2a = f2a();
+ expect(true, c2a is Class2);
+
+ dynamic f2b = Class2.named;
+ var c2b = f2b();
+ expect(true, c2b is Class2);
+
+ expect(true, identical(f2a, f2b));
+}
+
+class Class3 {
+ final int field;
+
+ Class3._(this.field);
+ factory Class3(int field) = Class3._;
+}
+
+class Class4 {
+ final int? field;
+
+ Class4._([this.field]);
+ factory Class4([int? field]) = Class4._;
+}
+
+class Class5 {
+ final int field1;
+ final int? field2;
+
+ Class5._(this.field1, [this.field2]);
+ factory Class5(int field1, [int? field2]) = Class5._;
+}
+
+class Class6 {
+ final int field1;
+ final int? field2;
+ final int field3;
+
+ Class6._(this.field1, {this.field2, required this.field3});
+ factory Class6(int field1, {int? field2, required int field3}) =
+ Class6._;
+}
+
+testArgs() {
+ var f3a = Class3.new;
+ var c3a = f3a(42);
+ expect(42, c3a.field);
+ () {
+ f3a(); // error
+ f3a(42, 87); // error
+ };
+
+ dynamic f3b = Class3.new;
+ var c3b = f3b(87);
+ expect(87, c3b.field);
+ throws(() => f3b());
+ throws(() => f3b(42, 87));
+
+ var f4a = Class4.new;
+ var c4a = f4a();
+ expect(null, c4a.field);
+ var c4b = f4a(42);
+ expect(42, c4b.field);
+ () {
+ f4a(42, 87); // error
+ };
+ dynamic f4b = Class4.new;
+ throws(() => f4b(42, 87));
+
+
+ var f5a = Class5.new;
+ var c5a = f5a(42);
+ expect(42, c5a.field1);
+ expect(null, c5a.field2);
+ var c5b = f5a(87, 42);
+ expect(87, c5b.field1);
+ expect(42, c5b.field2);
+ () {
+ f5a(); // error
+ f5a(42, 87, 123); // error
+ };
+ dynamic f5b = Class5.new;
+ throws(() => f5b());
+ throws(() => f5b(42, 87, 123));
+
+ var f6a = Class6.new;
+ var c6a = f6a(42, field3: 87);
+ expect(42, c6a.field1);
+ expect(null, c6a.field2);
+ expect(87, c6a.field3);
+ () {
+ f6a(); // error
+ f6a(42); // error
+ f6a(42, 87); // error
+ f6a(field1: 87, field2: 87); // error
+ };
+
+ var c6b = f6a(42, field2: 123, field3: 87);
+ expect(42, c6b.field1);
+ expect(123, c6b.field2);
+ expect(87, c6b.field3);
+
+ var c6c = f6a(87, field3: 42, field2: 123);
+ expect(87, c6c.field1);
+ expect(123, c6c.field2);
+ expect(42, c6c.field3);
+
+ dynamic f6b = Class6.new;
+ throws(() => f6b());
+ throws(() => f6b(42), inSoundModeOnly: true);
+ throws(() => f6b(42, 87), inSoundModeOnly: true);
+ throws(() => f6b(field1: 87, field2: 87));
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+ try {
+ f();
+ } catch (e) {
+ print('Thrown: $e');
+ return;
+ }
+ if (!inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw 'Expected exception';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.strong.expect
new file mode 100644
index 0000000..f2dd642
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.strong.expect
@@ -0,0 +1,236 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f4a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+// f5a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+// f5a(42, 87, 123); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+// f6a(42); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f6a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(field1: 87, field2: 87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _() → self::Class1
+ : super core::Object::•()
+ ;
+ static factory •() → self::Class1
+ let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+}
+class Class2 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+ constructor _() → self::Class2
+ : super core::Object::•()
+ ;
+ static factory named() → self::Class2
+ let dynamic #redirecting_factory = self::Class2::_ in invalid-expression;
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+ constructor _(core::int field) → self::Class3
+ : self::Class3::field = field, super core::Object::•()
+ ;
+ static factory •(core::int field) → self::Class3
+ let dynamic #redirecting_factory = self::Class3::_ in invalid-expression;
+}
+class Class4 extends core::Object {
+ final field core::int? field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+ constructor _([core::int? field = #C1]) → self::Class4
+ : self::Class4::field = field, super core::Object::•()
+ ;
+ static factory •([core::int? field = #C1]) → self::Class4
+ let dynamic #redirecting_factory = self::Class4::_ in invalid-expression;
+}
+class Class5 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+ constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+ ;
+ static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ let dynamic #redirecting_factory = self::Class5::_ in invalid-expression;
+}
+class Class6 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ final field core::int field3;
+ static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+ constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+ ;
+ static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ let dynamic #redirecting_factory = self::Class6::_ in invalid-expression;
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testNoArgs();
+ self::testArgs();
+}
+static method testNoArgs() → dynamic {
+ () → self::Class1 f1a = #C2;
+ self::Class1 c1a = f1a(){() → self::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+ dynamic f1b = #C2;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+ self::expect(true, core::identical(f1a, f1b));
+ () → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){() → self::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+ dynamic f2b = #C3;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+ self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+ (core::int) → self::Class3 f3a = #C4;
+ self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+ self::expect(42, c3a.{self::Class3::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3a(); // error
+ ^" in f3a{<inapplicable>}.();
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3a(42, 87); // error
+ ^" in f3a{<inapplicable>}.(42, 87);
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call(87);
+ self::expect(87, c3b{dynamic}.field);
+ self::throws(() → dynamic => f3b{dynamic}.call());
+ self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+ ([core::int?]) → self::Class4 f4a = #C5;
+ self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+ self::expect(null, c4a.{self::Class4::field}{core::int?});
+ self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+ self::expect(42, c4b.{self::Class4::field}{core::int?});
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f4a(42, 87); // error
+ ^" in f4a{<inapplicable>}.(42, 87);
+ };
+ dynamic f4b = #C5;
+ self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+ (core::int, [core::int?]) → self::Class5 f5a = #C6;
+ self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+ self::expect(42, c5a.{self::Class5::field1}{core::int});
+ self::expect(null, c5a.{self::Class5::field2}{core::int?});
+ self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+ self::expect(87, c5b.{self::Class5::field1}{core::int});
+ self::expect(42, c5b.{self::Class5::field2}{core::int?});
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+ f5a(); // error
+ ^" in f5a{<inapplicable>}.();
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+ f5a(42, 87, 123); // error
+ ^" in f5a{<inapplicable>}.(42, 87, 123);
+ };
+ dynamic f5b = #C6;
+ self::throws(() → dynamic => f5b{dynamic}.call());
+ self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+ (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+ self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6a.{self::Class6::field1}{core::int});
+ self::expect(null, c6a.{self::Class6::field2}{core::int?});
+ self::expect(87, c6a.{self::Class6::field3}{core::int});
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(); // error
+ ^" in f6a{<inapplicable>}.();
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+ f6a(42); // error
+ ^" in f6a{<inapplicable>}.(42);
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f6a(42, 87); // error
+ ^" in f6a{<inapplicable>}.(42, 87);
+ let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(field1: 87, field2: 87); // error
+ ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+ };
+ self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6b.{self::Class6::field1}{core::int});
+ self::expect(123, c6b.{self::Class6::field2}{core::int?});
+ self::expect(87, c6b.{self::Class6::field3}{core::int});
+ self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(87, c6c.{self::Class6::field1}{core::int});
+ self::expect(123, c6c.{self::Class6::field2}{core::int?});
+ self::expect(42, c6c.{self::Class6::field3}{core::int});
+ dynamic f6b = #C7;
+ self::throws(() → dynamic => f6b{dynamic}.call());
+ self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C8}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = null
+ #C2 = redirecting-factory-tearoff self::Class1::•
+ #C3 = redirecting-factory-tearoff self::Class2::named
+ #C4 = redirecting-factory-tearoff self::Class3::•
+ #C5 = redirecting-factory-tearoff self::Class4::•
+ #C6 = redirecting-factory-tearoff self::Class5::•
+ #C7 = redirecting-factory-tearoff self::Class6::•
+ #C8 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..ccaec42
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,236 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f4a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+// f5a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+// f5a(42, 87, 123); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+// f6a(42); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f6a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(field1: 87, field2: 87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _() → self::Class1
+ : super core::Object::•()
+ ;
+ static factory •() → self::Class1
+ let Never #redirecting_factory = self::Class1::_ in invalid-expression;
+}
+class Class2 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+ constructor _() → self::Class2
+ : super core::Object::•()
+ ;
+ static factory named() → self::Class2
+ let Never #redirecting_factory = self::Class2::_ in invalid-expression;
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+ constructor _(core::int field) → self::Class3
+ : self::Class3::field = field, super core::Object::•()
+ ;
+ static factory •(core::int field) → self::Class3
+ let Never #redirecting_factory = self::Class3::_ in invalid-expression;
+}
+class Class4 extends core::Object {
+ final field core::int? field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+ constructor _([core::int? field = #C1]) → self::Class4
+ : self::Class4::field = field, super core::Object::•()
+ ;
+ static factory •([core::int? field = #C1]) → self::Class4
+ let Never #redirecting_factory = self::Class4::_ in invalid-expression;
+}
+class Class5 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+ constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+ ;
+ static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ let Never #redirecting_factory = self::Class5::_ in invalid-expression;
+}
+class Class6 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ final field core::int field3;
+ static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+ constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+ ;
+ static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ let Never #redirecting_factory = self::Class6::_ in invalid-expression;
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testNoArgs();
+ self::testArgs();
+}
+static method testNoArgs() → dynamic {
+ () → self::Class1 f1a = #C2;
+ self::Class1 c1a = f1a(){() → self::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+ dynamic f1b = #C2;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+ self::expect(true, core::identical(f1a, f1b));
+ () → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){() → self::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+ dynamic f2b = #C3;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+ self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+ (core::int) → self::Class3 f3a = #C4;
+ self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+ self::expect(42, c3a.{self::Class3::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3a(); // error
+ ^" in f3a{<inapplicable>}.();
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3a(42, 87); // error
+ ^" in f3a{<inapplicable>}.(42, 87);
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call(87);
+ self::expect(87, c3b{dynamic}.field);
+ self::throws(() → dynamic => f3b{dynamic}.call());
+ self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+ ([core::int?]) → self::Class4 f4a = #C5;
+ self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+ self::expect(null, c4a.{self::Class4::field}{core::int?});
+ self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+ self::expect(42, c4b.{self::Class4::field}{core::int?});
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f4a(42, 87); // error
+ ^" in f4a{<inapplicable>}.(42, 87);
+ };
+ dynamic f4b = #C5;
+ self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+ (core::int, [core::int?]) → self::Class5 f5a = #C6;
+ self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+ self::expect(42, c5a.{self::Class5::field1}{core::int});
+ self::expect(null, c5a.{self::Class5::field2}{core::int?});
+ self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+ self::expect(87, c5b.{self::Class5::field1}{core::int});
+ self::expect(42, c5b.{self::Class5::field2}{core::int?});
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+ f5a(); // error
+ ^" in f5a{<inapplicable>}.();
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+ f5a(42, 87, 123); // error
+ ^" in f5a{<inapplicable>}.(42, 87, 123);
+ };
+ dynamic f5b = #C6;
+ self::throws(() → dynamic => f5b{dynamic}.call());
+ self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+ (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+ self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6a.{self::Class6::field1}{core::int});
+ self::expect(null, c6a.{self::Class6::field2}{core::int?});
+ self::expect(87, c6a.{self::Class6::field3}{core::int});
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(); // error
+ ^" in f6a{<inapplicable>}.();
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+ f6a(42); // error
+ ^" in f6a{<inapplicable>}.(42);
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f6a(42, 87); // error
+ ^" in f6a{<inapplicable>}.(42, 87);
+ let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(field1: 87, field2: 87); // error
+ ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+ };
+ self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6b.{self::Class6::field1}{core::int});
+ self::expect(123, c6b.{self::Class6::field2}{core::int?});
+ self::expect(87, c6b.{self::Class6::field3}{core::int});
+ self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(87, c6c.{self::Class6::field1}{core::int});
+ self::expect(123, c6c.{self::Class6::field2}{core::int?});
+ self::expect(42, c6c.{self::Class6::field3}{core::int});
+ dynamic f6b = #C7;
+ self::throws(() → dynamic => f6b{dynamic}.call());
+ self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C8}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = null
+ #C2 = redirecting-factory-tearoff self::Class1::•
+ #C3 = redirecting-factory-tearoff self::Class2::named
+ #C4 = redirecting-factory-tearoff self::Class3::•
+ #C5 = redirecting-factory-tearoff self::Class4::•
+ #C6 = redirecting-factory-tearoff self::Class5::•
+ #C7 = redirecting-factory-tearoff self::Class6::•
+ #C8 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..999b5d2
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.textual_outline.expect
@@ -0,0 +1,45 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+
+class Class1 {
+ Class1._();
+ factory Class1() = Class1._;
+}
+
+class Class2 {
+ Class2._();
+ factory Class2.named() = Class2._;
+}
+
+testNoArgs() {}
+
+class Class3 {
+ final int field;
+ Class3._(this.field);
+ factory Class3(int field) = Class3._;
+}
+
+class Class4 {
+ final int? field;
+ Class4._([this.field]);
+ factory Class4([int? field]) = Class4._;
+}
+
+class Class5 {
+ final int field1;
+ final int? field2;
+ Class5._(this.field1, [this.field2]);
+ factory Class5(int field1, [int? field2]) = Class5._;
+}
+
+class Class6 {
+ final int field1;
+ final int? field2;
+ final int field3;
+ Class6._(this.field1, {this.field2, required this.field3});
+ factory Class6(int field1, {int? field2, required int field3}) = Class6._;
+}
+
+testArgs() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..edb4f68
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.textual_outline_modelled.expect
@@ -0,0 +1,43 @@
+class Class1 {
+ Class1._();
+ factory Class1() = Class1._;
+}
+
+class Class2 {
+ Class2._();
+ factory Class2.named() = Class2._;
+}
+
+class Class3 {
+ Class3._(this.field);
+ factory Class3(int field) = Class3._;
+ final int field;
+}
+
+class Class4 {
+ Class4._([this.field]);
+ factory Class4([int? field]) = Class4._;
+ final int? field;
+}
+
+class Class5 {
+ Class5._(this.field1, [this.field2]);
+ factory Class5(int field1, [int? field2]) = Class5._;
+ final int? field2;
+ final int field1;
+}
+
+class Class6 {
+ Class6._(this.field1, {this.field2, required this.field3});
+ factory Class6(int field1, {int? field2, required int field3}) = Class6._;
+ final int? field2;
+ final int field1;
+ final int field3;
+}
+
+expect(expected, actual) {}
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+testArgs() {}
+testNoArgs() {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.expect
new file mode 100644
index 0000000..f2dd642
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.expect
@@ -0,0 +1,236 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f4a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+// f5a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+// f5a(42, 87, 123); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+// f6a(42); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f6a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(field1: 87, field2: 87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _() → self::Class1
+ : super core::Object::•()
+ ;
+ static factory •() → self::Class1
+ let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+}
+class Class2 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+ constructor _() → self::Class2
+ : super core::Object::•()
+ ;
+ static factory named() → self::Class2
+ let dynamic #redirecting_factory = self::Class2::_ in invalid-expression;
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+ constructor _(core::int field) → self::Class3
+ : self::Class3::field = field, super core::Object::•()
+ ;
+ static factory •(core::int field) → self::Class3
+ let dynamic #redirecting_factory = self::Class3::_ in invalid-expression;
+}
+class Class4 extends core::Object {
+ final field core::int? field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+ constructor _([core::int? field = #C1]) → self::Class4
+ : self::Class4::field = field, super core::Object::•()
+ ;
+ static factory •([core::int? field = #C1]) → self::Class4
+ let dynamic #redirecting_factory = self::Class4::_ in invalid-expression;
+}
+class Class5 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+ constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+ ;
+ static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ let dynamic #redirecting_factory = self::Class5::_ in invalid-expression;
+}
+class Class6 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ final field core::int field3;
+ static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+ constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+ ;
+ static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ let dynamic #redirecting_factory = self::Class6::_ in invalid-expression;
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testNoArgs();
+ self::testArgs();
+}
+static method testNoArgs() → dynamic {
+ () → self::Class1 f1a = #C2;
+ self::Class1 c1a = f1a(){() → self::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+ dynamic f1b = #C2;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+ self::expect(true, core::identical(f1a, f1b));
+ () → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){() → self::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+ dynamic f2b = #C3;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+ self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+ (core::int) → self::Class3 f3a = #C4;
+ self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+ self::expect(42, c3a.{self::Class3::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3a(); // error
+ ^" in f3a{<inapplicable>}.();
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3a(42, 87); // error
+ ^" in f3a{<inapplicable>}.(42, 87);
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call(87);
+ self::expect(87, c3b{dynamic}.field);
+ self::throws(() → dynamic => f3b{dynamic}.call());
+ self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+ ([core::int?]) → self::Class4 f4a = #C5;
+ self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+ self::expect(null, c4a.{self::Class4::field}{core::int?});
+ self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+ self::expect(42, c4b.{self::Class4::field}{core::int?});
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f4a(42, 87); // error
+ ^" in f4a{<inapplicable>}.(42, 87);
+ };
+ dynamic f4b = #C5;
+ self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+ (core::int, [core::int?]) → self::Class5 f5a = #C6;
+ self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+ self::expect(42, c5a.{self::Class5::field1}{core::int});
+ self::expect(null, c5a.{self::Class5::field2}{core::int?});
+ self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+ self::expect(87, c5b.{self::Class5::field1}{core::int});
+ self::expect(42, c5b.{self::Class5::field2}{core::int?});
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+ f5a(); // error
+ ^" in f5a{<inapplicable>}.();
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+ f5a(42, 87, 123); // error
+ ^" in f5a{<inapplicable>}.(42, 87, 123);
+ };
+ dynamic f5b = #C6;
+ self::throws(() → dynamic => f5b{dynamic}.call());
+ self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+ (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+ self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6a.{self::Class6::field1}{core::int});
+ self::expect(null, c6a.{self::Class6::field2}{core::int?});
+ self::expect(87, c6a.{self::Class6::field3}{core::int});
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(); // error
+ ^" in f6a{<inapplicable>}.();
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+ f6a(42); // error
+ ^" in f6a{<inapplicable>}.(42);
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f6a(42, 87); // error
+ ^" in f6a{<inapplicable>}.(42, 87);
+ let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(field1: 87, field2: 87); // error
+ ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+ };
+ self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6b.{self::Class6::field1}{core::int});
+ self::expect(123, c6b.{self::Class6::field2}{core::int?});
+ self::expect(87, c6b.{self::Class6::field3}{core::int});
+ self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(87, c6c.{self::Class6::field1}{core::int});
+ self::expect(123, c6c.{self::Class6::field2}{core::int?});
+ self::expect(42, c6c.{self::Class6::field3}{core::int});
+ dynamic f6b = #C7;
+ self::throws(() → dynamic => f6b{dynamic}.call());
+ self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C8}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = null
+ #C2 = redirecting-factory-tearoff self::Class1::•
+ #C3 = redirecting-factory-tearoff self::Class2::named
+ #C4 = redirecting-factory-tearoff self::Class3::•
+ #C5 = redirecting-factory-tearoff self::Class4::•
+ #C6 = redirecting-factory-tearoff self::Class5::•
+ #C7 = redirecting-factory-tearoff self::Class6::•
+ #C8 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..44ac319
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.outline.expect
@@ -0,0 +1,64 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _() → self::Class1
+ ;
+ static factory •() → self::Class1
+ let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+}
+class Class2 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+ constructor _() → self::Class2
+ ;
+ static factory named() → self::Class2
+ let dynamic #redirecting_factory = self::Class2::_ in invalid-expression;
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+ constructor _(core::int field) → self::Class3
+ ;
+ static factory •(core::int field) → self::Class3
+ let dynamic #redirecting_factory = self::Class3::_ in invalid-expression;
+}
+class Class4 extends core::Object {
+ final field core::int? field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+ constructor _([core::int? field]) → self::Class4
+ ;
+ static factory •([core::int? field]) → self::Class4
+ let dynamic #redirecting_factory = self::Class4::_ in invalid-expression;
+}
+class Class5 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+ constructor _(core::int field1, [core::int? field2]) → self::Class5
+ ;
+ static factory •(core::int field1, [core::int? field2]) → self::Class5
+ let dynamic #redirecting_factory = self::Class5::_ in invalid-expression;
+}
+class Class6 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ final field core::int field3;
+ static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+ constructor _(core::int field1, {core::int? field2, required core::int field3}) → self::Class6
+ ;
+ static factory •(core::int field1, {core::int? field2, required core::int field3}) → self::Class6
+ let dynamic #redirecting_factory = self::Class6::_ in invalid-expression;
+}
+static final field core::bool inSoundMode;
+static method main() → dynamic
+ ;
+static method testNoArgs() → dynamic
+ ;
+static method testArgs() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..ccaec42
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,236 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f4a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+// f5a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+// f5a(42, 87, 123); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+// f6a(42); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f6a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(field1: 87, field2: 87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _() → self::Class1
+ : super core::Object::•()
+ ;
+ static factory •() → self::Class1
+ let Never #redirecting_factory = self::Class1::_ in invalid-expression;
+}
+class Class2 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+ constructor _() → self::Class2
+ : super core::Object::•()
+ ;
+ static factory named() → self::Class2
+ let Never #redirecting_factory = self::Class2::_ in invalid-expression;
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+ constructor _(core::int field) → self::Class3
+ : self::Class3::field = field, super core::Object::•()
+ ;
+ static factory •(core::int field) → self::Class3
+ let Never #redirecting_factory = self::Class3::_ in invalid-expression;
+}
+class Class4 extends core::Object {
+ final field core::int? field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+ constructor _([core::int? field = #C1]) → self::Class4
+ : self::Class4::field = field, super core::Object::•()
+ ;
+ static factory •([core::int? field = #C1]) → self::Class4
+ let Never #redirecting_factory = self::Class4::_ in invalid-expression;
+}
+class Class5 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+ constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+ ;
+ static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ let Never #redirecting_factory = self::Class5::_ in invalid-expression;
+}
+class Class6 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ final field core::int field3;
+ static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+ constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+ ;
+ static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ let Never #redirecting_factory = self::Class6::_ in invalid-expression;
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testNoArgs();
+ self::testArgs();
+}
+static method testNoArgs() → dynamic {
+ () → self::Class1 f1a = #C2;
+ self::Class1 c1a = f1a(){() → self::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+ dynamic f1b = #C2;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+ self::expect(true, core::identical(f1a, f1b));
+ () → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){() → self::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+ dynamic f2b = #C3;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+ self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+ (core::int) → self::Class3 f3a = #C4;
+ self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+ self::expect(42, c3a.{self::Class3::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3a(); // error
+ ^" in f3a{<inapplicable>}.();
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3a(42, 87); // error
+ ^" in f3a{<inapplicable>}.(42, 87);
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call(87);
+ self::expect(87, c3b{dynamic}.field);
+ self::throws(() → dynamic => f3b{dynamic}.call());
+ self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+ ([core::int?]) → self::Class4 f4a = #C5;
+ self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+ self::expect(null, c4a.{self::Class4::field}{core::int?});
+ self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+ self::expect(42, c4b.{self::Class4::field}{core::int?});
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f4a(42, 87); // error
+ ^" in f4a{<inapplicable>}.(42, 87);
+ };
+ dynamic f4b = #C5;
+ self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+ (core::int, [core::int?]) → self::Class5 f5a = #C6;
+ self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+ self::expect(42, c5a.{self::Class5::field1}{core::int});
+ self::expect(null, c5a.{self::Class5::field2}{core::int?});
+ self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+ self::expect(87, c5b.{self::Class5::field1}{core::int});
+ self::expect(42, c5b.{self::Class5::field2}{core::int?});
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+ f5a(); // error
+ ^" in f5a{<inapplicable>}.();
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+ f5a(42, 87, 123); // error
+ ^" in f5a{<inapplicable>}.(42, 87, 123);
+ };
+ dynamic f5b = #C6;
+ self::throws(() → dynamic => f5b{dynamic}.call());
+ self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+ (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+ self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6a.{self::Class6::field1}{core::int});
+ self::expect(null, c6a.{self::Class6::field2}{core::int?});
+ self::expect(87, c6a.{self::Class6::field3}{core::int});
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(); // error
+ ^" in f6a{<inapplicable>}.();
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+ f6a(42); // error
+ ^" in f6a{<inapplicable>}.(42);
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f6a(42, 87); // error
+ ^" in f6a{<inapplicable>}.(42, 87);
+ let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(field1: 87, field2: 87); // error
+ ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+ };
+ self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6b.{self::Class6::field1}{core::int});
+ self::expect(123, c6b.{self::Class6::field2}{core::int?});
+ self::expect(87, c6b.{self::Class6::field3}{core::int});
+ self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(87, c6c.{self::Class6::field1}{core::int});
+ self::expect(123, c6c.{self::Class6::field2}{core::int?});
+ self::expect(42, c6c.{self::Class6::field3}{core::int});
+ dynamic f6b = #C7;
+ self::throws(() → dynamic => f6b{dynamic}.call());
+ self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C8}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = null
+ #C2 = redirecting-factory-tearoff self::Class1::•
+ #C3 = redirecting-factory-tearoff self::Class2::named
+ #C4 = redirecting-factory-tearoff self::Class3::•
+ #C5 = redirecting-factory-tearoff self::Class4::•
+ #C6 = redirecting-factory-tearoff self::Class5::•
+ #C7 = redirecting-factory-tearoff self::Class6::•
+ #C8 = false
+}
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index cfb0715..d6b5325 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -9,6 +9,7 @@
dart2js/late_statics: SemiFuzzFailure # dartbug.com/45854
constructor_tearoffs/redirecting_constructors: RuntimeError
+constructor_tearoffs/redirecting_factory_tear_off: RuntimeError
extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
extension_types/issue45775: ExpectationFileMismatchSerialized # Expected.
extension_types/simple: ExpectationFileMismatchSerialized # Expected.
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 82cb3b9..81314ea 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -12,7 +12,8 @@
constructor_tearoffs/instantiation: TextSerializationFailure
constructor_tearoffs/nongeneric_tearoff_with_context: TextSerializationFailure
constructor_tearoffs/nongeneric_tearoff_without_context: TextSerializationFailure
-constructor_tearoffs/redirecting_constructors: RuntimeError
+constructor_tearoffs/redirecting_constructors: TextSerializationFailure
+constructor_tearoffs/redirecting_factory_tear_off: TextSerializationFailure
constructor_tearoffs/typedef_tearoffs: TextSerializationFailure
constructor_tearoffs/unnamed_constructor: TextSerializationFailure
extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index 82c2ba6..f69c2ec 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -12,6 +12,7 @@
dart2js/late_statics: SemiFuzzFailure # dartbug.com/45854
constructor_tearoffs/redirecting_constructors: RuntimeError
+constructor_tearoffs/redirecting_factory_tear_off: RuntimeError
extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
extension_types/issue45775: ExpectationFileMismatchSerialized # Expected.
extension_types/simple: ExpectationFileMismatchSerialized # Expected.
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index b6b135c..06cd777 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -373,6 +373,8 @@
return _readStaticTearOffConstant();
case ConstantTag.ConstructorTearOffConstant:
return _readConstructorTearOffConstant();
+ case ConstantTag.RedirectingFactoryTearOffConstant:
+ return _readRedirectingFactoryTearOffConstant();
case ConstantTag.TypeLiteralConstant:
return _readTypeLiteralConstant();
case ConstantTag.UnevaluatedConstant:
@@ -470,6 +472,11 @@
return new ConstructorTearOffConstant.byReference(reference);
}
+ Constant _readRedirectingFactoryTearOffConstant() {
+ final Reference reference = readNonNullCanonicalNameReference().reference;
+ return new RedirectingFactoryTearOffConstant.byReference(reference);
+ }
+
Constant _readTypeLiteralConstant() {
final DartType type = readDartType();
return new TypeLiteralConstant(type);
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index 837bfc7..b2666d8 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -2048,6 +2048,10 @@
writeMemberReferenceFromReference(node.targetReference);
}
+ visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) {
+ writeMemberReferenceFromReference(node.targetReference);
+ }
+
visitTypedefTearOff(TypedefTearOff node) {
writeTypeParameterList(node.typeParameters);
state = SYMBOL;
@@ -2721,6 +2725,17 @@
endLine();
}
+ visitRedirectingFactoryTearOffConstant(
+ RedirectingFactoryTearOffConstant node) {
+ writeIndentation();
+ writeConstantReference(node);
+ writeSpaced('=');
+ writeWord('redirecting-factory-tearoff');
+ writeSpace();
+ writeMemberReferenceFromReference(node.targetReference);
+ endLine();
+ }
+
defaultNode(Node node) {
write('<${node.runtimeType}>');
}
diff --git a/tools/VERSION b/tools/VERSION
index 46fd44a..5b933e1 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 14
PATCH 0
-PRERELEASE 338
+PRERELEASE 339
PRERELEASE_PATCH 0
\ No newline at end of file