Version 2.17.0-182.2.beta
* Cherry-pick 5090974cf37b54e81d65614bd52ea020261ac93c to beta
diff --git a/pkg/front_end/lib/src/fasta/scope.dart b/pkg/front_end/lib/src/fasta/scope.dart
index 300080b..b4c0a0a 100644
--- a/pkg/front_end/lib/src/fasta/scope.dart
+++ b/pkg/front_end/lib/src/fasta/scope.dart
@@ -805,7 +805,7 @@
}
@override
- LibraryBuilder get library {
+ SourceLibraryBuilder get library {
throw new UnsupportedError('AmbiguousMemberBuilder.library');
}
diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
index 0fe0d36..bbadbf0 100644
--- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
@@ -2809,6 +2809,9 @@
: super(field, parent);
@override
+ SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
+
+ @override
void buildOutlineExpressions(
SourceLibraryBuilder library,
ClassHierarchy classHierarchy,
diff --git a/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart b/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
index 06f77cb..eee8284 100644
--- a/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
@@ -130,9 +130,6 @@
compilationUnit, charOffset, nativeMethodName);
@override
- SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
-
- @override
SourceClassBuilder get classBuilder =>
super.classBuilder as SourceClassBuilder;
@@ -783,6 +780,9 @@
_synthesizedFunctionNode = synthesizedFunctionNode,
super(constructor, constructorTearOff, parent);
+ @override
+ SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
+
// TODO(johnniwinther,cstefantsova): Rename [actualOrigin] to avoid the
// confusion with patches.
MemberBuilder? get actualOrigin {
diff --git a/pkg/front_end/lib/src/fasta/source/source_factory_builder.dart b/pkg/front_end/lib/src/fasta/source/source_factory_builder.dart
index 16072e5..edf0831 100644
--- a/pkg/front_end/lib/src/fasta/source/source_factory_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_factory_builder.dart
@@ -407,6 +407,11 @@
inferrer.helper = library.loader.createBodyBuilderForOutlineExpression(
library, classBuilder, this, classBuilder!.scope, fileUri);
Builder? targetBuilder = redirectionTarget.target;
+ if (targetBuilder is SourceMemberBuilder) {
+ // Ensure that target has been built.
+ targetBuilder.buildOutlineExpressions(targetBuilder.library,
+ classHierarchy, delayedActionPerformers, synthesizedFunctionNodes);
+ }
if (targetBuilder is FunctionBuilder) {
target = targetBuilder.member;
} else if (targetBuilder is DillMemberBuilder) {
@@ -457,14 +462,34 @@
new RedirectingFactoryBody(target, typeArguments, function);
function.body!.parent = function;
}
- if (_factoryTearOff != null &&
- (target is Constructor || target is Procedure && target.isFactory)) {
- synthesizedFunctionNodes.add(buildRedirectingFactoryTearOffBody(
- _factoryTearOff!,
- target!,
- typeArguments ?? [],
- _tearOffTypeParameters!,
- library));
+ if (_factoryTearOff != null) {
+ Set<Procedure> seenTargets = {};
+ while (target is Procedure && target.isRedirectingFactory) {
+ if (!seenTargets.add(target)) {
+ // Cyclic dependency.
+ target = null;
+ break;
+ }
+ RedirectingFactoryBody body =
+ target.function.body as RedirectingFactoryBody;
+ if (typeArguments != null) {
+ Substitution substitution = Substitution.fromPairs(
+ target.function.typeParameters, typeArguments);
+ typeArguments =
+ body.typeArguments?.map(substitution.substituteType).toList();
+ } else {
+ typeArguments = body.typeArguments;
+ }
+ target = body.target;
+ }
+ if (target is Constructor || target is Procedure && target.isFactory) {
+ synthesizedFunctionNodes.add(buildRedirectingFactoryTearOffBody(
+ _factoryTearOff!,
+ target!,
+ typeArguments ?? [],
+ _tearOffTypeParameters!,
+ library));
+ }
}
if (isConst && isPatch) {
_finishPatch();
diff --git a/pkg/front_end/lib/src/fasta/source/source_field_builder.dart b/pkg/front_end/lib/src/fasta/source/source_field_builder.dart
index 0f2b052..6735bb3 100644
--- a/pkg/front_end/lib/src/fasta/source/source_field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_field_builder.dart
@@ -283,9 +283,6 @@
}
@override
- SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
-
- @override
Member get member => _fieldEncoding.field;
@override
diff --git a/pkg/front_end/lib/src/fasta/source/source_member_builder.dart b/pkg/front_end/lib/src/fasta/source/source_member_builder.dart
index f4cf938..9b8a08d 100644
--- a/pkg/front_end/lib/src/fasta/source/source_member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_member_builder.dart
@@ -25,6 +25,9 @@
abstract class SourceMemberBuilder implements MemberBuilder {
MemberDataForTesting? get dataForTesting;
+ @override
+ SourceLibraryBuilder get library;
+
/// Builds the core AST structures for this member as needed for the outline.
void buildMembers(
SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f);
@@ -87,6 +90,9 @@
retainDataForTesting ? new MemberDataForTesting() : null,
super(parent, charOffset, fileUri);
+ @override
+ SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
+
bool get isRedirectingGenerativeConstructor => false;
@override
diff --git a/pkg/front_end/testcases/dart2js/issue47916.dart b/pkg/front_end/testcases/dart2js/issue47916.dart
new file mode 100644
index 0000000..a00eec3
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2022, 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.
+
+abstract class A {
+ const factory A() = B;
+}
+
+abstract class B implements A {
+ const factory B() = C;
+}
+
+class C implements B {
+ const C();
+}
+
+main() {
+ A.new;
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916.dart.strong.expect b/pkg/front_end/testcases/dart2js/issue47916.dart.strong.expect
new file mode 100644
index 0000000..2ff6c91
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916.dart.strong.expect
@@ -0,0 +1,34 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •() → self::A
+ return self::B::•();
+ static method _#new#tearOff() → self::A
+ return new self::C::•();
+}
+abstract class B extends core::Object implements self::A {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •() → self::B
+ return new self::C::•();
+ static method _#new#tearOff() → self::B
+ return new self::C::•();
+}
+class C extends core::Object implements self::B /*hasConstConstructor*/ {
+ const constructor •() → self::C
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::C
+ return new self::C::•();
+}
+static method main() → dynamic {
+ #C3;
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = static-tearoff self::A::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2js/issue47916.dart.strong.transformed.expect
new file mode 100644
index 0000000..2ff6c91
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916.dart.strong.transformed.expect
@@ -0,0 +1,34 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •() → self::A
+ return self::B::•();
+ static method _#new#tearOff() → self::A
+ return new self::C::•();
+}
+abstract class B extends core::Object implements self::A {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •() → self::B
+ return new self::C::•();
+ static method _#new#tearOff() → self::B
+ return new self::C::•();
+}
+class C extends core::Object implements self::B /*hasConstConstructor*/ {
+ const constructor •() → self::C
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::C
+ return new self::C::•();
+}
+static method main() → dynamic {
+ #C3;
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = static-tearoff self::A::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916.dart.textual_outline.expect b/pkg/front_end/testcases/dart2js/issue47916.dart.textual_outline.expect
new file mode 100644
index 0000000..7bfc84b
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916.dart.textual_outline.expect
@@ -0,0 +1,13 @@
+abstract class A {
+ const factory A() = B;
+}
+
+abstract class B implements A {
+ const factory B() = C;
+}
+
+class C implements B {
+ const C();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/dart2js/issue47916.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dart2js/issue47916.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..7bfc84b
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916.dart.textual_outline_modelled.expect
@@ -0,0 +1,13 @@
+abstract class A {
+ const factory A() = B;
+}
+
+abstract class B implements A {
+ const factory B() = C;
+}
+
+class C implements B {
+ const C();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/dart2js/issue47916.dart.weak.expect b/pkg/front_end/testcases/dart2js/issue47916.dart.weak.expect
new file mode 100644
index 0000000..2ff6c91
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916.dart.weak.expect
@@ -0,0 +1,34 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •() → self::A
+ return self::B::•();
+ static method _#new#tearOff() → self::A
+ return new self::C::•();
+}
+abstract class B extends core::Object implements self::A {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •() → self::B
+ return new self::C::•();
+ static method _#new#tearOff() → self::B
+ return new self::C::•();
+}
+class C extends core::Object implements self::B /*hasConstConstructor*/ {
+ const constructor •() → self::C
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::C
+ return new self::C::•();
+}
+static method main() → dynamic {
+ #C3;
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = static-tearoff self::A::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916.dart.weak.modular.expect b/pkg/front_end/testcases/dart2js/issue47916.dart.weak.modular.expect
new file mode 100644
index 0000000..2ff6c91
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916.dart.weak.modular.expect
@@ -0,0 +1,34 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •() → self::A
+ return self::B::•();
+ static method _#new#tearOff() → self::A
+ return new self::C::•();
+}
+abstract class B extends core::Object implements self::A {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •() → self::B
+ return new self::C::•();
+ static method _#new#tearOff() → self::B
+ return new self::C::•();
+}
+class C extends core::Object implements self::B /*hasConstConstructor*/ {
+ const constructor •() → self::C
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::C
+ return new self::C::•();
+}
+static method main() → dynamic {
+ #C3;
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = static-tearoff self::A::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916.dart.weak.outline.expect b/pkg/front_end/testcases/dart2js/issue47916.dart.weak.outline.expect
new file mode 100644
index 0000000..287ad71
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916.dart.weak.outline.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::A::•]/*isLegacy*/;
+ static factory •() → self::A
+ return self::B::•();
+ static method _#new#tearOff() → self::A
+ return new self::C::•();
+}
+abstract class B extends core::Object implements self::A {
+ static final field dynamic _redirecting# = <dynamic>[self::B::•]/*isLegacy*/;
+ static factory •() → self::B
+ return new self::C::•();
+ static method _#new#tearOff() → self::B
+ return new self::C::•();
+}
+class C extends core::Object implements self::B /*hasConstConstructor*/ {
+ const constructor •() → self::C
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::C
+ return new self::C::•();
+}
+static method main() → dynamic
+ ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///issue47916.dart:5:16 -> ConstructorTearOffConstant(A.)
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///issue47916.dart:9:16 -> ConstructorTearOffConstant(B.)
+Extra constant evaluation: evaluated: 9, effectively constant: 2
diff --git a/pkg/front_end/testcases/dart2js/issue47916.dart.weak.transformed.expect b/pkg/front_end/testcases/dart2js/issue47916.dart.weak.transformed.expect
new file mode 100644
index 0000000..2ff6c91
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916.dart.weak.transformed.expect
@@ -0,0 +1,34 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •() → self::A
+ return self::B::•();
+ static method _#new#tearOff() → self::A
+ return new self::C::•();
+}
+abstract class B extends core::Object implements self::A {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •() → self::B
+ return new self::C::•();
+ static method _#new#tearOff() → self::B
+ return new self::C::•();
+}
+class C extends core::Object implements self::B /*hasConstConstructor*/ {
+ const constructor •() → self::C
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::C
+ return new self::C::•();
+}
+static method main() → dynamic {
+ #C3;
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = static-tearoff self::A::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916b.dart b/pkg/front_end/testcases/dart2js/issue47916b.dart
new file mode 100644
index 0000000..b6ff812
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916b.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2022, 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.
+
+abstract class A<T> {
+ const factory A() = B;
+}
+
+abstract class B<S, T> implements A<T> {
+ const factory B() = C;
+}
+
+class C<T, S, U> implements B<S, T> {
+ const C();
+}
+
+main() {
+ A<int>.new;
+ B<String, double>.new;
+ C<bool, num, void>.new;
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916b.dart.strong.expect b/pkg/front_end/testcases/dart2js/issue47916b.dart.strong.expect
new file mode 100644
index 0000000..7eb2968
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916b.dart.strong.expect
@@ -0,0 +1,41 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::A<self::A::•::T%>
+ return self::B::•<dynamic, self::A::•::T%>();
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>
+ return new self::C::•<self::A::_#new#tearOff::T%, dynamic, dynamic>();
+}
+abstract class B<S extends core::Object? = dynamic, T extends core::Object? = dynamic> extends core::Object implements self::A<self::B::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •<S extends core::Object? = dynamic, T extends core::Object? = dynamic>() → self::B<self::B::•::S%, self::B::•::T%>
+ return new self::C::•<self::B::•::T%, self::B::•::S%, dynamic>();
+ static method _#new#tearOff<S extends core::Object? = dynamic, T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::S%, self::B::_#new#tearOff::T%>
+ return new self::C::•<self::B::_#new#tearOff::T%, self::B::_#new#tearOff::S%, dynamic>();
+}
+class C<T extends core::Object? = dynamic, S extends core::Object? = dynamic, U extends core::Object? = dynamic> extends core::Object implements self::B<self::C::S%, self::C::T%> /*hasConstConstructor*/ {
+ const constructor •() → self::C<self::C::T%, self::C::S%, self::C::U%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic, S extends core::Object? = dynamic, U extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%, self::C::_#new#tearOff::S%, self::C::_#new#tearOff::U%>
+ return new self::C::•<self::C::_#new#tearOff::T%, self::C::_#new#tearOff::S%, self::C::_#new#tearOff::U%>();
+}
+static method main() → dynamic {
+ #C4;
+ #C6;
+ #C8;
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = static-tearoff self::A::_#new#tearOff
+ #C4 = instantiation #C3 <core::int>
+ #C5 = static-tearoff self::B::_#new#tearOff
+ #C6 = instantiation #C5 <core::String, core::double>
+ #C7 = static-tearoff self::C::_#new#tearOff
+ #C8 = instantiation #C7 <core::bool, core::num, void>
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916b.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2js/issue47916b.dart.strong.transformed.expect
new file mode 100644
index 0000000..7eb2968
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916b.dart.strong.transformed.expect
@@ -0,0 +1,41 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::A<self::A::•::T%>
+ return self::B::•<dynamic, self::A::•::T%>();
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>
+ return new self::C::•<self::A::_#new#tearOff::T%, dynamic, dynamic>();
+}
+abstract class B<S extends core::Object? = dynamic, T extends core::Object? = dynamic> extends core::Object implements self::A<self::B::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •<S extends core::Object? = dynamic, T extends core::Object? = dynamic>() → self::B<self::B::•::S%, self::B::•::T%>
+ return new self::C::•<self::B::•::T%, self::B::•::S%, dynamic>();
+ static method _#new#tearOff<S extends core::Object? = dynamic, T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::S%, self::B::_#new#tearOff::T%>
+ return new self::C::•<self::B::_#new#tearOff::T%, self::B::_#new#tearOff::S%, dynamic>();
+}
+class C<T extends core::Object? = dynamic, S extends core::Object? = dynamic, U extends core::Object? = dynamic> extends core::Object implements self::B<self::C::S%, self::C::T%> /*hasConstConstructor*/ {
+ const constructor •() → self::C<self::C::T%, self::C::S%, self::C::U%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic, S extends core::Object? = dynamic, U extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%, self::C::_#new#tearOff::S%, self::C::_#new#tearOff::U%>
+ return new self::C::•<self::C::_#new#tearOff::T%, self::C::_#new#tearOff::S%, self::C::_#new#tearOff::U%>();
+}
+static method main() → dynamic {
+ #C4;
+ #C6;
+ #C8;
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = static-tearoff self::A::_#new#tearOff
+ #C4 = instantiation #C3 <core::int>
+ #C5 = static-tearoff self::B::_#new#tearOff
+ #C6 = instantiation #C5 <core::String, core::double>
+ #C7 = static-tearoff self::C::_#new#tearOff
+ #C8 = instantiation #C7 <core::bool, core::num, void>
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916b.dart.textual_outline.expect b/pkg/front_end/testcases/dart2js/issue47916b.dart.textual_outline.expect
new file mode 100644
index 0000000..7fca510
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916b.dart.textual_outline.expect
@@ -0,0 +1,13 @@
+abstract class A<T> {
+ const factory A() = B;
+}
+
+abstract class B<S, T> implements A<T> {
+ const factory B() = C;
+}
+
+class C<T, S, U> implements B<S, T> {
+ const C();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/dart2js/issue47916b.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dart2js/issue47916b.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..7fca510
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916b.dart.textual_outline_modelled.expect
@@ -0,0 +1,13 @@
+abstract class A<T> {
+ const factory A() = B;
+}
+
+abstract class B<S, T> implements A<T> {
+ const factory B() = C;
+}
+
+class C<T, S, U> implements B<S, T> {
+ const C();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/dart2js/issue47916b.dart.weak.expect b/pkg/front_end/testcases/dart2js/issue47916b.dart.weak.expect
new file mode 100644
index 0000000..c35d6f8
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916b.dart.weak.expect
@@ -0,0 +1,41 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::A<self::A::•::T%>
+ return self::B::•<dynamic, self::A::•::T%>();
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>
+ return new self::C::•<self::A::_#new#tearOff::T%, dynamic, dynamic>();
+}
+abstract class B<S extends core::Object? = dynamic, T extends core::Object? = dynamic> extends core::Object implements self::A<self::B::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •<S extends core::Object? = dynamic, T extends core::Object? = dynamic>() → self::B<self::B::•::S%, self::B::•::T%>
+ return new self::C::•<self::B::•::T%, self::B::•::S%, dynamic>();
+ static method _#new#tearOff<S extends core::Object? = dynamic, T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::S%, self::B::_#new#tearOff::T%>
+ return new self::C::•<self::B::_#new#tearOff::T%, self::B::_#new#tearOff::S%, dynamic>();
+}
+class C<T extends core::Object? = dynamic, S extends core::Object? = dynamic, U extends core::Object? = dynamic> extends core::Object implements self::B<self::C::S%, self::C::T%> /*hasConstConstructor*/ {
+ const constructor •() → self::C<self::C::T%, self::C::S%, self::C::U%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic, S extends core::Object? = dynamic, U extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%, self::C::_#new#tearOff::S%, self::C::_#new#tearOff::U%>
+ return new self::C::•<self::C::_#new#tearOff::T%, self::C::_#new#tearOff::S%, self::C::_#new#tearOff::U%>();
+}
+static method main() → dynamic {
+ #C4;
+ #C6;
+ #C8;
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = static-tearoff self::A::_#new#tearOff
+ #C4 = instantiation #C3 <core::int*>
+ #C5 = static-tearoff self::B::_#new#tearOff
+ #C6 = instantiation #C5 <core::String*, core::double*>
+ #C7 = static-tearoff self::C::_#new#tearOff
+ #C8 = instantiation #C7 <core::bool*, core::num*, void>
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916b.dart.weak.modular.expect b/pkg/front_end/testcases/dart2js/issue47916b.dart.weak.modular.expect
new file mode 100644
index 0000000..c35d6f8
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916b.dart.weak.modular.expect
@@ -0,0 +1,41 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::A<self::A::•::T%>
+ return self::B::•<dynamic, self::A::•::T%>();
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>
+ return new self::C::•<self::A::_#new#tearOff::T%, dynamic, dynamic>();
+}
+abstract class B<S extends core::Object? = dynamic, T extends core::Object? = dynamic> extends core::Object implements self::A<self::B::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •<S extends core::Object? = dynamic, T extends core::Object? = dynamic>() → self::B<self::B::•::S%, self::B::•::T%>
+ return new self::C::•<self::B::•::T%, self::B::•::S%, dynamic>();
+ static method _#new#tearOff<S extends core::Object? = dynamic, T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::S%, self::B::_#new#tearOff::T%>
+ return new self::C::•<self::B::_#new#tearOff::T%, self::B::_#new#tearOff::S%, dynamic>();
+}
+class C<T extends core::Object? = dynamic, S extends core::Object? = dynamic, U extends core::Object? = dynamic> extends core::Object implements self::B<self::C::S%, self::C::T%> /*hasConstConstructor*/ {
+ const constructor •() → self::C<self::C::T%, self::C::S%, self::C::U%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic, S extends core::Object? = dynamic, U extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%, self::C::_#new#tearOff::S%, self::C::_#new#tearOff::U%>
+ return new self::C::•<self::C::_#new#tearOff::T%, self::C::_#new#tearOff::S%, self::C::_#new#tearOff::U%>();
+}
+static method main() → dynamic {
+ #C4;
+ #C6;
+ #C8;
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = static-tearoff self::A::_#new#tearOff
+ #C4 = instantiation #C3 <core::int*>
+ #C5 = static-tearoff self::B::_#new#tearOff
+ #C6 = instantiation #C5 <core::String*, core::double*>
+ #C7 = static-tearoff self::C::_#new#tearOff
+ #C8 = instantiation #C7 <core::bool*, core::num*, void>
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916b.dart.weak.outline.expect b/pkg/front_end/testcases/dart2js/issue47916b.dart.weak.outline.expect
new file mode 100644
index 0000000..fa68b8b
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916b.dart.weak.outline.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::A::•]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::A<self::A::•::T%>
+ return self::B::•<dynamic, self::A::•::T%>();
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>
+ return new self::C::•<self::A::_#new#tearOff::T%, dynamic, dynamic>();
+}
+abstract class B<S extends core::Object? = dynamic, T extends core::Object? = dynamic> extends core::Object implements self::A<self::B::T%> {
+ static final field dynamic _redirecting# = <dynamic>[self::B::•]/*isLegacy*/;
+ static factory •<S extends core::Object? = dynamic, T extends core::Object? = dynamic>() → self::B<self::B::•::S%, self::B::•::T%>
+ return new self::C::•<self::B::•::T%, self::B::•::S%, dynamic>();
+ static method _#new#tearOff<S extends core::Object? = dynamic, T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::S%, self::B::_#new#tearOff::T%>
+ return new self::C::•<self::B::_#new#tearOff::T%, self::B::_#new#tearOff::S%, dynamic>();
+}
+class C<T extends core::Object? = dynamic, S extends core::Object? = dynamic, U extends core::Object? = dynamic> extends core::Object implements self::B<self::C::S%, self::C::T%> /*hasConstConstructor*/ {
+ const constructor •() → self::C<self::C::T%, self::C::S%, self::C::U%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic, S extends core::Object? = dynamic, U extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%, self::C::_#new#tearOff::S%, self::C::_#new#tearOff::U%>
+ return new self::C::•<self::C::_#new#tearOff::T%, self::C::_#new#tearOff::S%, self::C::_#new#tearOff::U%>();
+}
+static method main() → dynamic
+ ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///issue47916b.dart:5:16 -> ConstructorTearOffConstant(A.)
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///issue47916b.dart:9:16 -> ConstructorTearOffConstant(B.)
+Extra constant evaluation: evaluated: 9, effectively constant: 2
diff --git a/pkg/front_end/testcases/dart2js/issue47916b.dart.weak.transformed.expect b/pkg/front_end/testcases/dart2js/issue47916b.dart.weak.transformed.expect
new file mode 100644
index 0000000..c35d6f8
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916b.dart.weak.transformed.expect
@@ -0,0 +1,41 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::A<self::A::•::T%>
+ return self::B::•<dynamic, self::A::•::T%>();
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>
+ return new self::C::•<self::A::_#new#tearOff::T%, dynamic, dynamic>();
+}
+abstract class B<S extends core::Object? = dynamic, T extends core::Object? = dynamic> extends core::Object implements self::A<self::B::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •<S extends core::Object? = dynamic, T extends core::Object? = dynamic>() → self::B<self::B::•::S%, self::B::•::T%>
+ return new self::C::•<self::B::•::T%, self::B::•::S%, dynamic>();
+ static method _#new#tearOff<S extends core::Object? = dynamic, T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::S%, self::B::_#new#tearOff::T%>
+ return new self::C::•<self::B::_#new#tearOff::T%, self::B::_#new#tearOff::S%, dynamic>();
+}
+class C<T extends core::Object? = dynamic, S extends core::Object? = dynamic, U extends core::Object? = dynamic> extends core::Object implements self::B<self::C::S%, self::C::T%> /*hasConstConstructor*/ {
+ const constructor •() → self::C<self::C::T%, self::C::S%, self::C::U%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic, S extends core::Object? = dynamic, U extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%, self::C::_#new#tearOff::S%, self::C::_#new#tearOff::U%>
+ return new self::C::•<self::C::_#new#tearOff::T%, self::C::_#new#tearOff::S%, self::C::_#new#tearOff::U%>();
+}
+static method main() → dynamic {
+ #C4;
+ #C6;
+ #C8;
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = static-tearoff self::A::_#new#tearOff
+ #C4 = instantiation #C3 <core::int*>
+ #C5 = static-tearoff self::B::_#new#tearOff
+ #C6 = instantiation #C5 <core::String*, core::double*>
+ #C7 = static-tearoff self::C::_#new#tearOff
+ #C8 = instantiation #C7 <core::bool*, core::num*, void>
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916c.dart b/pkg/front_end/testcases/dart2js/issue47916c.dart
new file mode 100644
index 0000000..4ba641d
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916c.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2022, 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.
+
+abstract class A {
+ const factory A() = B;
+}
+
+abstract class B implements A {
+ const factory B() = C<int>;
+}
+
+class C<T> implements B {
+ const C();
+}
+
+main() {
+ A.new;
+ B.new;
+ C<String>.new;
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916c.dart.strong.expect b/pkg/front_end/testcases/dart2js/issue47916c.dart.strong.expect
new file mode 100644
index 0000000..3eaff6e
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916c.dart.strong.expect
@@ -0,0 +1,39 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •() → self::A
+ return self::B::•();
+ static method _#new#tearOff() → self::A
+ return new self::C::•<core::int>();
+}
+abstract class B extends core::Object implements self::A {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •() → self::B
+ return new self::C::•<core::int>();
+ static method _#new#tearOff() → self::B
+ return new self::C::•<core::int>();
+}
+class C<T extends core::Object? = dynamic> extends core::Object implements self::B /*hasConstConstructor*/ {
+ const constructor •() → self::C<self::C::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>
+ return new self::C::•<self::C::_#new#tearOff::T%>();
+}
+static method main() → dynamic {
+ #C3;
+ #C4;
+ #C6;
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = static-tearoff self::A::_#new#tearOff
+ #C4 = static-tearoff self::B::_#new#tearOff
+ #C5 = static-tearoff self::C::_#new#tearOff
+ #C6 = instantiation #C5 <core::String>
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916c.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2js/issue47916c.dart.strong.transformed.expect
new file mode 100644
index 0000000..3eaff6e
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916c.dart.strong.transformed.expect
@@ -0,0 +1,39 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •() → self::A
+ return self::B::•();
+ static method _#new#tearOff() → self::A
+ return new self::C::•<core::int>();
+}
+abstract class B extends core::Object implements self::A {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •() → self::B
+ return new self::C::•<core::int>();
+ static method _#new#tearOff() → self::B
+ return new self::C::•<core::int>();
+}
+class C<T extends core::Object? = dynamic> extends core::Object implements self::B /*hasConstConstructor*/ {
+ const constructor •() → self::C<self::C::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>
+ return new self::C::•<self::C::_#new#tearOff::T%>();
+}
+static method main() → dynamic {
+ #C3;
+ #C4;
+ #C6;
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = static-tearoff self::A::_#new#tearOff
+ #C4 = static-tearoff self::B::_#new#tearOff
+ #C5 = static-tearoff self::C::_#new#tearOff
+ #C6 = instantiation #C5 <core::String>
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916c.dart.textual_outline.expect b/pkg/front_end/testcases/dart2js/issue47916c.dart.textual_outline.expect
new file mode 100644
index 0000000..33f910e
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916c.dart.textual_outline.expect
@@ -0,0 +1,13 @@
+abstract class A {
+ const factory A() = B;
+}
+
+abstract class B implements A {
+ const factory B() = C<int>;
+}
+
+class C<T> implements B {
+ const C();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/dart2js/issue47916c.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dart2js/issue47916c.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..33f910e
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916c.dart.textual_outline_modelled.expect
@@ -0,0 +1,13 @@
+abstract class A {
+ const factory A() = B;
+}
+
+abstract class B implements A {
+ const factory B() = C<int>;
+}
+
+class C<T> implements B {
+ const C();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/dart2js/issue47916c.dart.weak.expect b/pkg/front_end/testcases/dart2js/issue47916c.dart.weak.expect
new file mode 100644
index 0000000..8340651
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916c.dart.weak.expect
@@ -0,0 +1,39 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •() → self::A
+ return self::B::•();
+ static method _#new#tearOff() → self::A
+ return new self::C::•<core::int>();
+}
+abstract class B extends core::Object implements self::A {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •() → self::B
+ return new self::C::•<core::int>();
+ static method _#new#tearOff() → self::B
+ return new self::C::•<core::int>();
+}
+class C<T extends core::Object? = dynamic> extends core::Object implements self::B /*hasConstConstructor*/ {
+ const constructor •() → self::C<self::C::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>
+ return new self::C::•<self::C::_#new#tearOff::T%>();
+}
+static method main() → dynamic {
+ #C3;
+ #C4;
+ #C6;
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = static-tearoff self::A::_#new#tearOff
+ #C4 = static-tearoff self::B::_#new#tearOff
+ #C5 = static-tearoff self::C::_#new#tearOff
+ #C6 = instantiation #C5 <core::String*>
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916c.dart.weak.modular.expect b/pkg/front_end/testcases/dart2js/issue47916c.dart.weak.modular.expect
new file mode 100644
index 0000000..8340651
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916c.dart.weak.modular.expect
@@ -0,0 +1,39 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •() → self::A
+ return self::B::•();
+ static method _#new#tearOff() → self::A
+ return new self::C::•<core::int>();
+}
+abstract class B extends core::Object implements self::A {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •() → self::B
+ return new self::C::•<core::int>();
+ static method _#new#tearOff() → self::B
+ return new self::C::•<core::int>();
+}
+class C<T extends core::Object? = dynamic> extends core::Object implements self::B /*hasConstConstructor*/ {
+ const constructor •() → self::C<self::C::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>
+ return new self::C::•<self::C::_#new#tearOff::T%>();
+}
+static method main() → dynamic {
+ #C3;
+ #C4;
+ #C6;
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = static-tearoff self::A::_#new#tearOff
+ #C4 = static-tearoff self::B::_#new#tearOff
+ #C5 = static-tearoff self::C::_#new#tearOff
+ #C6 = instantiation #C5 <core::String*>
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916c.dart.weak.outline.expect b/pkg/front_end/testcases/dart2js/issue47916c.dart.weak.outline.expect
new file mode 100644
index 0000000..a3086c6
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916c.dart.weak.outline.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::A::•]/*isLegacy*/;
+ static factory •() → self::A
+ return self::B::•();
+ static method _#new#tearOff() → self::A
+ return new self::C::•<core::int>();
+}
+abstract class B extends core::Object implements self::A {
+ static final field dynamic _redirecting# = <dynamic>[self::B::•]/*isLegacy*/;
+ static factory •() → self::B
+ return new self::C::•<core::int>();
+ static method _#new#tearOff() → self::B
+ return new self::C::•<core::int>();
+}
+class C<T extends core::Object? = dynamic> extends core::Object implements self::B /*hasConstConstructor*/ {
+ const constructor •() → self::C<self::C::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>
+ return new self::C::•<self::C::_#new#tearOff::T%>();
+}
+static method main() → dynamic
+ ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///issue47916c.dart:5:16 -> ConstructorTearOffConstant(A.)
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///issue47916c.dart:9:16 -> ConstructorTearOffConstant(B.)
+Extra constant evaluation: evaluated: 9, effectively constant: 2
diff --git a/pkg/front_end/testcases/dart2js/issue47916c.dart.weak.transformed.expect b/pkg/front_end/testcases/dart2js/issue47916c.dart.weak.transformed.expect
new file mode 100644
index 0000000..8340651
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916c.dart.weak.transformed.expect
@@ -0,0 +1,39 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •() → self::A
+ return self::B::•();
+ static method _#new#tearOff() → self::A
+ return new self::C::•<core::int>();
+}
+abstract class B extends core::Object implements self::A {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •() → self::B
+ return new self::C::•<core::int>();
+ static method _#new#tearOff() → self::B
+ return new self::C::•<core::int>();
+}
+class C<T extends core::Object? = dynamic> extends core::Object implements self::B /*hasConstConstructor*/ {
+ const constructor •() → self::C<self::C::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>
+ return new self::C::•<self::C::_#new#tearOff::T%>();
+}
+static method main() → dynamic {
+ #C3;
+ #C4;
+ #C6;
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = static-tearoff self::A::_#new#tearOff
+ #C4 = static-tearoff self::B::_#new#tearOff
+ #C5 = static-tearoff self::C::_#new#tearOff
+ #C6 = instantiation #C5 <core::String*>
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916d.dart b/pkg/front_end/testcases/dart2js/issue47916d.dart
new file mode 100644
index 0000000..b51794e
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916d.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2022, 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.
+
+abstract class A<T> {
+ const factory A() = B;
+}
+
+abstract class B<T> implements A<T> {
+ const factory B() = C;
+}
+
+class C<T> implements B<T> {
+ const factory C() = A;
+}
+
+test() {
+ A.new;
+ B.new;
+ C.new;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/dart2js/issue47916d.dart.strong.expect b/pkg/front_end/testcases/dart2js/issue47916d.dart.strong.expect
new file mode 100644
index 0000000..b45f14a
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916d.dart.strong.expect
@@ -0,0 +1,58 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/issue47916d.dart:6:17: Error: Cyclic definition of factory 'A'.
+// const factory A() = B;
+// ^
+//
+// pkg/front_end/testcases/dart2js/issue47916d.dart:10:17: Error: Cyclic definition of factory 'B'.
+// const factory B() = C;
+// ^
+//
+// pkg/front_end/testcases/dart2js/issue47916d.dart:14:17: Error: Cyclic definition of factory 'C'.
+// const factory C() = A;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::A<self::A::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916d.dart:6:17: Error: Cyclic definition of factory 'A'.
+ const factory A() = B;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>;
+}
+abstract class B<T extends core::Object? = dynamic> extends core::Object implements self::A<self::B::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::B<self::B::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916d.dart:10:17: Error: Cyclic definition of factory 'B'.
+ const factory B() = C;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::T%>;
+}
+class C<T extends core::Object? = dynamic> extends core::Object implements self::B<self::C::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C3]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::C<self::C::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916d.dart:14:17: Error: Cyclic definition of factory 'C'.
+ const factory C() = A;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>;
+}
+static method test() → dynamic {
+ #C4;
+ #C5;
+ #C6;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = constructor-tearoff self::C::•
+ #C4 = static-tearoff self::A::_#new#tearOff
+ #C5 = static-tearoff self::B::_#new#tearOff
+ #C6 = static-tearoff self::C::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916d.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2js/issue47916d.dart.strong.transformed.expect
new file mode 100644
index 0000000..b45f14a
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916d.dart.strong.transformed.expect
@@ -0,0 +1,58 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/issue47916d.dart:6:17: Error: Cyclic definition of factory 'A'.
+// const factory A() = B;
+// ^
+//
+// pkg/front_end/testcases/dart2js/issue47916d.dart:10:17: Error: Cyclic definition of factory 'B'.
+// const factory B() = C;
+// ^
+//
+// pkg/front_end/testcases/dart2js/issue47916d.dart:14:17: Error: Cyclic definition of factory 'C'.
+// const factory C() = A;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::A<self::A::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916d.dart:6:17: Error: Cyclic definition of factory 'A'.
+ const factory A() = B;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>;
+}
+abstract class B<T extends core::Object? = dynamic> extends core::Object implements self::A<self::B::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::B<self::B::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916d.dart:10:17: Error: Cyclic definition of factory 'B'.
+ const factory B() = C;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::T%>;
+}
+class C<T extends core::Object? = dynamic> extends core::Object implements self::B<self::C::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C3]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::C<self::C::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916d.dart:14:17: Error: Cyclic definition of factory 'C'.
+ const factory C() = A;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>;
+}
+static method test() → dynamic {
+ #C4;
+ #C5;
+ #C6;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = constructor-tearoff self::C::•
+ #C4 = static-tearoff self::A::_#new#tearOff
+ #C5 = static-tearoff self::B::_#new#tearOff
+ #C6 = static-tearoff self::C::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916d.dart.textual_outline.expect b/pkg/front_end/testcases/dart2js/issue47916d.dart.textual_outline.expect
new file mode 100644
index 0000000..11b407c
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916d.dart.textual_outline.expect
@@ -0,0 +1,14 @@
+abstract class A<T> {
+ const factory A() = B;
+}
+
+abstract class B<T> implements A<T> {
+ const factory B() = C;
+}
+
+class C<T> implements B<T> {
+ const factory C() = A;
+}
+
+test() {}
+main() {}
diff --git a/pkg/front_end/testcases/dart2js/issue47916d.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dart2js/issue47916d.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..0b78e71
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916d.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+abstract class A<T> {
+ const factory A() = B;
+}
+
+abstract class B<T> implements A<T> {
+ const factory B() = C;
+}
+
+class C<T> implements B<T> {
+ const factory C() = A;
+}
+
+main() {}
+test() {}
diff --git a/pkg/front_end/testcases/dart2js/issue47916d.dart.weak.expect b/pkg/front_end/testcases/dart2js/issue47916d.dart.weak.expect
new file mode 100644
index 0000000..b45f14a
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916d.dart.weak.expect
@@ -0,0 +1,58 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/issue47916d.dart:6:17: Error: Cyclic definition of factory 'A'.
+// const factory A() = B;
+// ^
+//
+// pkg/front_end/testcases/dart2js/issue47916d.dart:10:17: Error: Cyclic definition of factory 'B'.
+// const factory B() = C;
+// ^
+//
+// pkg/front_end/testcases/dart2js/issue47916d.dart:14:17: Error: Cyclic definition of factory 'C'.
+// const factory C() = A;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::A<self::A::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916d.dart:6:17: Error: Cyclic definition of factory 'A'.
+ const factory A() = B;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>;
+}
+abstract class B<T extends core::Object? = dynamic> extends core::Object implements self::A<self::B::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::B<self::B::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916d.dart:10:17: Error: Cyclic definition of factory 'B'.
+ const factory B() = C;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::T%>;
+}
+class C<T extends core::Object? = dynamic> extends core::Object implements self::B<self::C::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C3]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::C<self::C::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916d.dart:14:17: Error: Cyclic definition of factory 'C'.
+ const factory C() = A;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>;
+}
+static method test() → dynamic {
+ #C4;
+ #C5;
+ #C6;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = constructor-tearoff self::C::•
+ #C4 = static-tearoff self::A::_#new#tearOff
+ #C5 = static-tearoff self::B::_#new#tearOff
+ #C6 = static-tearoff self::C::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916d.dart.weak.modular.expect b/pkg/front_end/testcases/dart2js/issue47916d.dart.weak.modular.expect
new file mode 100644
index 0000000..b45f14a
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916d.dart.weak.modular.expect
@@ -0,0 +1,58 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/issue47916d.dart:6:17: Error: Cyclic definition of factory 'A'.
+// const factory A() = B;
+// ^
+//
+// pkg/front_end/testcases/dart2js/issue47916d.dart:10:17: Error: Cyclic definition of factory 'B'.
+// const factory B() = C;
+// ^
+//
+// pkg/front_end/testcases/dart2js/issue47916d.dart:14:17: Error: Cyclic definition of factory 'C'.
+// const factory C() = A;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::A<self::A::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916d.dart:6:17: Error: Cyclic definition of factory 'A'.
+ const factory A() = B;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>;
+}
+abstract class B<T extends core::Object? = dynamic> extends core::Object implements self::A<self::B::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::B<self::B::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916d.dart:10:17: Error: Cyclic definition of factory 'B'.
+ const factory B() = C;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::T%>;
+}
+class C<T extends core::Object? = dynamic> extends core::Object implements self::B<self::C::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C3]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::C<self::C::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916d.dart:14:17: Error: Cyclic definition of factory 'C'.
+ const factory C() = A;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>;
+}
+static method test() → dynamic {
+ #C4;
+ #C5;
+ #C6;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = constructor-tearoff self::C::•
+ #C4 = static-tearoff self::A::_#new#tearOff
+ #C5 = static-tearoff self::B::_#new#tearOff
+ #C6 = static-tearoff self::C::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916d.dart.weak.outline.expect b/pkg/front_end/testcases/dart2js/issue47916d.dart.weak.outline.expect
new file mode 100644
index 0000000..ca9a4b0
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916d.dart.weak.outline.expect
@@ -0,0 +1,54 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/issue47916d.dart:6:17: Error: Cyclic definition of factory 'A'.
+// const factory A() = B;
+// ^
+//
+// pkg/front_end/testcases/dart2js/issue47916d.dart:10:17: Error: Cyclic definition of factory 'B'.
+// const factory B() = C;
+// ^
+//
+// pkg/front_end/testcases/dart2js/issue47916d.dart:14:17: Error: Cyclic definition of factory 'C'.
+// const factory C() = A;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::A::•]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::A<self::A::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916d.dart:6:17: Error: Cyclic definition of factory 'A'.
+ const factory A() = B;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>;
+}
+abstract class B<T extends core::Object? = dynamic> extends core::Object implements self::A<self::B::T%> {
+ static final field dynamic _redirecting# = <dynamic>[self::B::•]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::B<self::B::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916d.dart:10:17: Error: Cyclic definition of factory 'B'.
+ const factory B() = C;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::T%>;
+}
+class C<T extends core::Object? = dynamic> extends core::Object implements self::B<self::C::T%> {
+ static final field dynamic _redirecting# = <dynamic>[self::C::•]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::C<self::C::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916d.dart:14:17: Error: Cyclic definition of factory 'C'.
+ const factory C() = A;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>;
+}
+static method test() → dynamic
+ ;
+static method main() → dynamic
+ ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///issue47916d.dart:5:16 -> ConstructorTearOffConstant(A.)
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///issue47916d.dart:9:16 -> ConstructorTearOffConstant(B.)
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///issue47916d.dart:13:7 -> ConstructorTearOffConstant(C.)
+Extra constant evaluation: evaluated: 6, effectively constant: 3
diff --git a/pkg/front_end/testcases/dart2js/issue47916d.dart.weak.transformed.expect b/pkg/front_end/testcases/dart2js/issue47916d.dart.weak.transformed.expect
new file mode 100644
index 0000000..b45f14a
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916d.dart.weak.transformed.expect
@@ -0,0 +1,58 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/issue47916d.dart:6:17: Error: Cyclic definition of factory 'A'.
+// const factory A() = B;
+// ^
+//
+// pkg/front_end/testcases/dart2js/issue47916d.dart:10:17: Error: Cyclic definition of factory 'B'.
+// const factory B() = C;
+// ^
+//
+// pkg/front_end/testcases/dart2js/issue47916d.dart:14:17: Error: Cyclic definition of factory 'C'.
+// const factory C() = A;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::A<self::A::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916d.dart:6:17: Error: Cyclic definition of factory 'A'.
+ const factory A() = B;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>;
+}
+abstract class B<T extends core::Object? = dynamic> extends core::Object implements self::A<self::B::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::B<self::B::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916d.dart:10:17: Error: Cyclic definition of factory 'B'.
+ const factory B() = C;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::T%>;
+}
+class C<T extends core::Object? = dynamic> extends core::Object implements self::B<self::C::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C3]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::C<self::C::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916d.dart:14:17: Error: Cyclic definition of factory 'C'.
+ const factory C() = A;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>;
+}
+static method test() → dynamic {
+ #C4;
+ #C5;
+ #C6;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = constructor-tearoff self::C::•
+ #C4 = static-tearoff self::A::_#new#tearOff
+ #C5 = static-tearoff self::B::_#new#tearOff
+ #C6 = static-tearoff self::C::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916e.dart b/pkg/front_end/testcases/dart2js/issue47916e.dart
new file mode 100644
index 0000000..0c59128
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916e.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2022, 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.
+
+abstract class A {
+ const factory A() = B;
+}
+
+abstract class B implements A {
+ const factory B() = C.named;
+}
+
+class C implements B {
+ static C named() => new C();
+}
+
+test() {
+ A.new;
+ B.new;
+ C.named;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/dart2js/issue47916e.dart.strong.expect b/pkg/front_end/testcases/dart2js/issue47916e.dart.strong.expect
new file mode 100644
index 0000000..37a5606
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916e.dart.strong.expect
@@ -0,0 +1,48 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/issue47916e.dart:10:23: Error: Redirection constructor target not found: 'C.named'
+// const factory B() = C.named;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •() → self::A
+ return self::B::•();
+ static method _#new#tearOff() → self::A;
+}
+abstract class B extends core::Object implements self::A {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •() → self::B
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916e.dart:10:23: Error: Redirection constructor target not found: 'C.named'
+ const factory B() = C.named;
+ ^";
+ static method _#new#tearOff() → self::B;
+}
+class C extends core::Object implements self::B {
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+ static method named() → self::C
+ return new self::C::•();
+ static method _#new#tearOff() → self::C
+ return new self::C::•();
+}
+static method test() → dynamic {
+ #C3;
+ #C4;
+ #C5;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = static-tearoff self::A::_#new#tearOff
+ #C4 = static-tearoff self::B::_#new#tearOff
+ #C5 = static-tearoff self::C::named
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916e.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2js/issue47916e.dart.strong.transformed.expect
new file mode 100644
index 0000000..37a5606
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916e.dart.strong.transformed.expect
@@ -0,0 +1,48 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/issue47916e.dart:10:23: Error: Redirection constructor target not found: 'C.named'
+// const factory B() = C.named;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •() → self::A
+ return self::B::•();
+ static method _#new#tearOff() → self::A;
+}
+abstract class B extends core::Object implements self::A {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •() → self::B
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916e.dart:10:23: Error: Redirection constructor target not found: 'C.named'
+ const factory B() = C.named;
+ ^";
+ static method _#new#tearOff() → self::B;
+}
+class C extends core::Object implements self::B {
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+ static method named() → self::C
+ return new self::C::•();
+ static method _#new#tearOff() → self::C
+ return new self::C::•();
+}
+static method test() → dynamic {
+ #C3;
+ #C4;
+ #C5;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = static-tearoff self::A::_#new#tearOff
+ #C4 = static-tearoff self::B::_#new#tearOff
+ #C5 = static-tearoff self::C::named
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916e.dart.textual_outline.expect b/pkg/front_end/testcases/dart2js/issue47916e.dart.textual_outline.expect
new file mode 100644
index 0000000..504602f
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916e.dart.textual_outline.expect
@@ -0,0 +1,14 @@
+abstract class A {
+ const factory A() = B;
+}
+
+abstract class B implements A {
+ const factory B() = C.named;
+}
+
+class C implements B {
+ static C named() => new C();
+}
+
+test() {}
+main() {}
diff --git a/pkg/front_end/testcases/dart2js/issue47916e.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dart2js/issue47916e.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..66883b6
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916e.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+abstract class A {
+ const factory A() = B;
+}
+
+abstract class B implements A {
+ const factory B() = C.named;
+}
+
+class C implements B {
+ static C named() => new C();
+}
+
+main() {}
+test() {}
diff --git a/pkg/front_end/testcases/dart2js/issue47916e.dart.weak.expect b/pkg/front_end/testcases/dart2js/issue47916e.dart.weak.expect
new file mode 100644
index 0000000..37a5606
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916e.dart.weak.expect
@@ -0,0 +1,48 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/issue47916e.dart:10:23: Error: Redirection constructor target not found: 'C.named'
+// const factory B() = C.named;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •() → self::A
+ return self::B::•();
+ static method _#new#tearOff() → self::A;
+}
+abstract class B extends core::Object implements self::A {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •() → self::B
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916e.dart:10:23: Error: Redirection constructor target not found: 'C.named'
+ const factory B() = C.named;
+ ^";
+ static method _#new#tearOff() → self::B;
+}
+class C extends core::Object implements self::B {
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+ static method named() → self::C
+ return new self::C::•();
+ static method _#new#tearOff() → self::C
+ return new self::C::•();
+}
+static method test() → dynamic {
+ #C3;
+ #C4;
+ #C5;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = static-tearoff self::A::_#new#tearOff
+ #C4 = static-tearoff self::B::_#new#tearOff
+ #C5 = static-tearoff self::C::named
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916e.dart.weak.modular.expect b/pkg/front_end/testcases/dart2js/issue47916e.dart.weak.modular.expect
new file mode 100644
index 0000000..37a5606
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916e.dart.weak.modular.expect
@@ -0,0 +1,48 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/issue47916e.dart:10:23: Error: Redirection constructor target not found: 'C.named'
+// const factory B() = C.named;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •() → self::A
+ return self::B::•();
+ static method _#new#tearOff() → self::A;
+}
+abstract class B extends core::Object implements self::A {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •() → self::B
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916e.dart:10:23: Error: Redirection constructor target not found: 'C.named'
+ const factory B() = C.named;
+ ^";
+ static method _#new#tearOff() → self::B;
+}
+class C extends core::Object implements self::B {
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+ static method named() → self::C
+ return new self::C::•();
+ static method _#new#tearOff() → self::C
+ return new self::C::•();
+}
+static method test() → dynamic {
+ #C3;
+ #C4;
+ #C5;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = static-tearoff self::A::_#new#tearOff
+ #C4 = static-tearoff self::B::_#new#tearOff
+ #C5 = static-tearoff self::C::named
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916e.dart.weak.outline.expect b/pkg/front_end/testcases/dart2js/issue47916e.dart.weak.outline.expect
new file mode 100644
index 0000000..b57ce18
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916e.dart.weak.outline.expect
@@ -0,0 +1,43 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/issue47916e.dart:10:23: Error: Redirection constructor target not found: 'C.named'
+// const factory B() = C.named;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::A::•]/*isLegacy*/;
+ static factory •() → self::A
+ return self::B::•();
+ static method _#new#tearOff() → self::A;
+}
+abstract class B extends core::Object implements self::A {
+ static final field dynamic _redirecting# = <dynamic>[self::B::•]/*isLegacy*/;
+ static factory •() → self::B
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916e.dart:10:23: Error: Redirection constructor target not found: 'C.named'
+ const factory B() = C.named;
+ ^";
+ static method _#new#tearOff() → self::B;
+}
+class C extends core::Object implements self::B {
+ synthetic constructor •() → self::C
+ ;
+ static method named() → self::C
+ ;
+ static method _#new#tearOff() → self::C
+ return new self::C::•();
+}
+static method test() → dynamic
+ ;
+static method main() → dynamic
+ ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///issue47916e.dart:5:16 -> ConstructorTearOffConstant(A.)
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///issue47916e.dart:9:16 -> ConstructorTearOffConstant(B.)
+Extra constant evaluation: evaluated: 6, effectively constant: 2
diff --git a/pkg/front_end/testcases/dart2js/issue47916e.dart.weak.transformed.expect b/pkg/front_end/testcases/dart2js/issue47916e.dart.weak.transformed.expect
new file mode 100644
index 0000000..37a5606
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916e.dart.weak.transformed.expect
@@ -0,0 +1,48 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/issue47916e.dart:10:23: Error: Redirection constructor target not found: 'C.named'
+// const factory B() = C.named;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •() → self::A
+ return self::B::•();
+ static method _#new#tearOff() → self::A;
+}
+abstract class B extends core::Object implements self::A {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •() → self::B
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916e.dart:10:23: Error: Redirection constructor target not found: 'C.named'
+ const factory B() = C.named;
+ ^";
+ static method _#new#tearOff() → self::B;
+}
+class C extends core::Object implements self::B {
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+ static method named() → self::C
+ return new self::C::•();
+ static method _#new#tearOff() → self::C
+ return new self::C::•();
+}
+static method test() → dynamic {
+ #C3;
+ #C4;
+ #C5;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = static-tearoff self::A::_#new#tearOff
+ #C4 = static-tearoff self::B::_#new#tearOff
+ #C5 = static-tearoff self::C::named
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916f.dart b/pkg/front_end/testcases/dart2js/issue47916f.dart
new file mode 100644
index 0000000..4350d1d
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916f.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2022, 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.
+
+abstract class A<T> {
+ const factory A() = B;
+}
+
+abstract class B<T> implements A<T> {
+ const factory B() = C;
+}
+
+class C<T> implements B<T> {
+ const factory C() = B;
+}
+
+test() {
+ A.new;
+ B.new;
+ C.new;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/dart2js/issue47916f.dart.strong.expect b/pkg/front_end/testcases/dart2js/issue47916f.dart.strong.expect
new file mode 100644
index 0000000..9fbc39d
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916f.dart.strong.expect
@@ -0,0 +1,52 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/issue47916f.dart:10:17: Error: Cyclic definition of factory 'B'.
+// const factory B() = C;
+// ^
+//
+// pkg/front_end/testcases/dart2js/issue47916f.dart:14:17: Error: Cyclic definition of factory 'C'.
+// const factory C() = B;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::A<self::A::•::T%>
+ return self::B::•<self::A::•::T%>();
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>;
+}
+abstract class B<T extends core::Object? = dynamic> extends core::Object implements self::A<self::B::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::B<self::B::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916f.dart:10:17: Error: Cyclic definition of factory 'B'.
+ const factory B() = C;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::T%>;
+}
+class C<T extends core::Object? = dynamic> extends core::Object implements self::B<self::C::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C3]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::C<self::C::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916f.dart:14:17: Error: Cyclic definition of factory 'C'.
+ const factory C() = B;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>;
+}
+static method test() → dynamic {
+ #C4;
+ #C5;
+ #C6;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = constructor-tearoff self::C::•
+ #C4 = static-tearoff self::A::_#new#tearOff
+ #C5 = static-tearoff self::B::_#new#tearOff
+ #C6 = static-tearoff self::C::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916f.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2js/issue47916f.dart.strong.transformed.expect
new file mode 100644
index 0000000..9fbc39d
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916f.dart.strong.transformed.expect
@@ -0,0 +1,52 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/issue47916f.dart:10:17: Error: Cyclic definition of factory 'B'.
+// const factory B() = C;
+// ^
+//
+// pkg/front_end/testcases/dart2js/issue47916f.dart:14:17: Error: Cyclic definition of factory 'C'.
+// const factory C() = B;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::A<self::A::•::T%>
+ return self::B::•<self::A::•::T%>();
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>;
+}
+abstract class B<T extends core::Object? = dynamic> extends core::Object implements self::A<self::B::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::B<self::B::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916f.dart:10:17: Error: Cyclic definition of factory 'B'.
+ const factory B() = C;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::T%>;
+}
+class C<T extends core::Object? = dynamic> extends core::Object implements self::B<self::C::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C3]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::C<self::C::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916f.dart:14:17: Error: Cyclic definition of factory 'C'.
+ const factory C() = B;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>;
+}
+static method test() → dynamic {
+ #C4;
+ #C5;
+ #C6;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = constructor-tearoff self::C::•
+ #C4 = static-tearoff self::A::_#new#tearOff
+ #C5 = static-tearoff self::B::_#new#tearOff
+ #C6 = static-tearoff self::C::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916f.dart.textual_outline.expect b/pkg/front_end/testcases/dart2js/issue47916f.dart.textual_outline.expect
new file mode 100644
index 0000000..838563b
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916f.dart.textual_outline.expect
@@ -0,0 +1,14 @@
+abstract class A<T> {
+ const factory A() = B;
+}
+
+abstract class B<T> implements A<T> {
+ const factory B() = C;
+}
+
+class C<T> implements B<T> {
+ const factory C() = B;
+}
+
+test() {}
+main() {}
diff --git a/pkg/front_end/testcases/dart2js/issue47916f.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dart2js/issue47916f.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..7477d7b
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916f.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+abstract class A<T> {
+ const factory A() = B;
+}
+
+abstract class B<T> implements A<T> {
+ const factory B() = C;
+}
+
+class C<T> implements B<T> {
+ const factory C() = B;
+}
+
+main() {}
+test() {}
diff --git a/pkg/front_end/testcases/dart2js/issue47916f.dart.weak.expect b/pkg/front_end/testcases/dart2js/issue47916f.dart.weak.expect
new file mode 100644
index 0000000..9fbc39d
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916f.dart.weak.expect
@@ -0,0 +1,52 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/issue47916f.dart:10:17: Error: Cyclic definition of factory 'B'.
+// const factory B() = C;
+// ^
+//
+// pkg/front_end/testcases/dart2js/issue47916f.dart:14:17: Error: Cyclic definition of factory 'C'.
+// const factory C() = B;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::A<self::A::•::T%>
+ return self::B::•<self::A::•::T%>();
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>;
+}
+abstract class B<T extends core::Object? = dynamic> extends core::Object implements self::A<self::B::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::B<self::B::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916f.dart:10:17: Error: Cyclic definition of factory 'B'.
+ const factory B() = C;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::T%>;
+}
+class C<T extends core::Object? = dynamic> extends core::Object implements self::B<self::C::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C3]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::C<self::C::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916f.dart:14:17: Error: Cyclic definition of factory 'C'.
+ const factory C() = B;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>;
+}
+static method test() → dynamic {
+ #C4;
+ #C5;
+ #C6;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = constructor-tearoff self::C::•
+ #C4 = static-tearoff self::A::_#new#tearOff
+ #C5 = static-tearoff self::B::_#new#tearOff
+ #C6 = static-tearoff self::C::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916f.dart.weak.modular.expect b/pkg/front_end/testcases/dart2js/issue47916f.dart.weak.modular.expect
new file mode 100644
index 0000000..9fbc39d
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916f.dart.weak.modular.expect
@@ -0,0 +1,52 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/issue47916f.dart:10:17: Error: Cyclic definition of factory 'B'.
+// const factory B() = C;
+// ^
+//
+// pkg/front_end/testcases/dart2js/issue47916f.dart:14:17: Error: Cyclic definition of factory 'C'.
+// const factory C() = B;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::A<self::A::•::T%>
+ return self::B::•<self::A::•::T%>();
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>;
+}
+abstract class B<T extends core::Object? = dynamic> extends core::Object implements self::A<self::B::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::B<self::B::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916f.dart:10:17: Error: Cyclic definition of factory 'B'.
+ const factory B() = C;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::T%>;
+}
+class C<T extends core::Object? = dynamic> extends core::Object implements self::B<self::C::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C3]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::C<self::C::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916f.dart:14:17: Error: Cyclic definition of factory 'C'.
+ const factory C() = B;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>;
+}
+static method test() → dynamic {
+ #C4;
+ #C5;
+ #C6;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = constructor-tearoff self::C::•
+ #C4 = static-tearoff self::A::_#new#tearOff
+ #C5 = static-tearoff self::B::_#new#tearOff
+ #C6 = static-tearoff self::C::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/dart2js/issue47916f.dart.weak.outline.expect b/pkg/front_end/testcases/dart2js/issue47916f.dart.weak.outline.expect
new file mode 100644
index 0000000..7b1a696
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916f.dart.weak.outline.expect
@@ -0,0 +1,48 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/issue47916f.dart:10:17: Error: Cyclic definition of factory 'B'.
+// const factory B() = C;
+// ^
+//
+// pkg/front_end/testcases/dart2js/issue47916f.dart:14:17: Error: Cyclic definition of factory 'C'.
+// const factory C() = B;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::A::•]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::A<self::A::•::T%>
+ return self::B::•<self::A::•::T%>();
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>;
+}
+abstract class B<T extends core::Object? = dynamic> extends core::Object implements self::A<self::B::T%> {
+ static final field dynamic _redirecting# = <dynamic>[self::B::•]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::B<self::B::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916f.dart:10:17: Error: Cyclic definition of factory 'B'.
+ const factory B() = C;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::T%>;
+}
+class C<T extends core::Object? = dynamic> extends core::Object implements self::B<self::C::T%> {
+ static final field dynamic _redirecting# = <dynamic>[self::C::•]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::C<self::C::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916f.dart:14:17: Error: Cyclic definition of factory 'C'.
+ const factory C() = B;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>;
+}
+static method test() → dynamic
+ ;
+static method main() → dynamic
+ ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///issue47916f.dart:5:16 -> ConstructorTearOffConstant(A.)
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///issue47916f.dart:9:16 -> ConstructorTearOffConstant(B.)
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///issue47916f.dart:13:7 -> ConstructorTearOffConstant(C.)
+Extra constant evaluation: evaluated: 7, effectively constant: 3
diff --git a/pkg/front_end/testcases/dart2js/issue47916f.dart.weak.transformed.expect b/pkg/front_end/testcases/dart2js/issue47916f.dart.weak.transformed.expect
new file mode 100644
index 0000000..9fbc39d
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue47916f.dart.weak.transformed.expect
@@ -0,0 +1,52 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/dart2js/issue47916f.dart:10:17: Error: Cyclic definition of factory 'B'.
+// const factory B() = C;
+// ^
+//
+// pkg/front_end/testcases/dart2js/issue47916f.dart:14:17: Error: Cyclic definition of factory 'C'.
+// const factory C() = B;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::A<self::A::•::T%>
+ return self::B::•<self::A::•::T%>();
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>;
+}
+abstract class B<T extends core::Object? = dynamic> extends core::Object implements self::A<self::B::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::B<self::B::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916f.dart:10:17: Error: Cyclic definition of factory 'B'.
+ const factory B() = C;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::T%>;
+}
+class C<T extends core::Object? = dynamic> extends core::Object implements self::B<self::C::T%> {
+ static final field dynamic _redirecting# = <dynamic>[#C3]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::C<self::C::•::T%>
+ return invalid-expression "pkg/front_end/testcases/dart2js/issue47916f.dart:14:17: Error: Cyclic definition of factory 'C'.
+ const factory C() = B;
+ ^";
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>;
+}
+static method test() → dynamic {
+ #C4;
+ #C5;
+ #C6;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = constructor-tearoff self::B::•
+ #C3 = constructor-tearoff self::C::•
+ #C4 = static-tearoff self::A::_#new#tearOff
+ #C5 = static-tearoff self::B::_#new#tearOff
+ #C6 = static-tearoff self::C::_#new#tearOff
+}
diff --git a/tests/language/redirecting/issue47916_test.dart b/tests/language/redirecting/issue47916_test.dart
new file mode 100644
index 0000000..096aaf2
--- /dev/null
+++ b/tests/language/redirecting/issue47916_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2022, 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.
+
+/// Regression test for issue 47916. The CFE tear-off lowering for A.new
+/// called the immediate target B.new (which is also a redirecting factory)
+/// instead of the effective target C.new. This caused problem in backends
+/// that don't support redirecting factories directly.
+
+abstract class A {
+ const factory A() = B;
+}
+
+abstract class B implements A {
+ const factory B() = C;
+}
+
+class C implements B {
+ const C();
+}
+
+main() {
+ A.new;
+}
diff --git a/tools/VERSION b/tools/VERSION
index 441390e..1139bac 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
MINOR 17
PATCH 0
PRERELEASE 182
-PRERELEASE_PATCH 1
\ No newline at end of file
+PRERELEASE_PATCH 2
\ No newline at end of file