Version 2.16.2

* Cherry-pick refs/changes/41/238041/1 to stable
* Cherry-pick a999d2182c2f3f2fbceee96d616639c345d45108 to stable
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fbba72b..c722e0e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+## 2.16.2 - 2022-03-24
+
+This is a patch release that fixes a dart2js crash when building some Flutter
+web apps (issue [#47916][]).
+
+[#47916]: https://github.com/dart-lang/sdk/issues/47916
+
 ## 2.16.1 - 2022-02-09
 
 This is a patch release that fixes an AOT precompiler crash when building some
diff --git a/pkg/front_end/lib/src/fasta/builder/factory_builder.dart b/pkg/front_end/lib/src/fasta/builder/factory_builder.dart
index 86c7b96..32f016d 100644
--- a/pkg/front_end/lib/src/fasta/builder/factory_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/factory_builder.dart
@@ -396,6 +396,14 @@
       inferrer.helper = library.loader.createBodyBuilderForOutlineExpression(
           library, classBuilder, this, classBuilder!.scope, fileUri);
       Builder? targetBuilder = redirectionTarget.target;
+      if (targetBuilder is MemberBuilder) {
+        // Ensure that target has been built.
+        targetBuilder.buildOutlineExpressions(
+            targetBuilder.library as SourceLibraryBuilder,
+            coreTypes,
+            delayedActionPerformers,
+            synthesizedFunctionNodes);
+      }
       if (targetBuilder is FunctionBuilder) {
         target = targetBuilder.member;
       } else if (targetBuilder is DillMemberBuilder) {
@@ -446,13 +454,33 @@
           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!));
+    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!));
+      }
     }
     if (isConst && isPatch) {
       _finishPatch();
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 9be6324..e7ef658 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -26,6 +26,6 @@
 CHANNEL stable
 MAJOR 2
 MINOR 16
-PATCH 1
+PATCH 2
 PRERELEASE 0
 PRERELEASE_PATCH 0
\ No newline at end of file