Version 2.17.0-188.0.dev

Merge commit '7d115ed0ad6369723b13837357350a14f7afa9f8' into 'dev'
diff --git a/pkg/front_end/analysis_options_no_lints.yaml b/pkg/front_end/analysis_options_no_lints.yaml
index c1cae63..810d473 100644
--- a/pkg/front_end/analysis_options_no_lints.yaml
+++ b/pkg/front_end/analysis_options_no_lints.yaml
@@ -12,8 +12,8 @@
     - test/extensions/data/**
     - test/id_testing/data/**
     - test/language_versioning/data/**
-    - test/macro_application/data/**
-    - test/macros/data/**
+    - test/macros/application/data/**
+    - test/macros/declaration/data/**
     - test/patching/data/**
     - test/predicates/data/**
     - test/static_types/data/**
diff --git a/pkg/front_end/lib/src/fasta/scope.dart b/pkg/front_end/lib/src/fasta/scope.dart
index 300080b..b4c0a0a 100644
--- a/pkg/front_end/lib/src/fasta/scope.dart
+++ b/pkg/front_end/lib/src/fasta/scope.dart
@@ -805,7 +805,7 @@
   }
 
   @override
-  LibraryBuilder get library {
+  SourceLibraryBuilder get library {
     throw new UnsupportedError('AmbiguousMemberBuilder.library');
   }
 
diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
index 0fe0d36..bbadbf0 100644
--- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
@@ -2809,6 +2809,9 @@
       : super(field, parent);
 
   @override
+  SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
+
+  @override
   void buildOutlineExpressions(
       SourceLibraryBuilder library,
       ClassHierarchy classHierarchy,
diff --git a/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart b/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
index 06f77cb..eee8284 100644
--- a/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
@@ -130,9 +130,6 @@
             compilationUnit, charOffset, nativeMethodName);
 
   @override
-  SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
-
-  @override
   SourceClassBuilder get classBuilder =>
       super.classBuilder as SourceClassBuilder;
 
@@ -783,6 +780,9 @@
         _synthesizedFunctionNode = synthesizedFunctionNode,
         super(constructor, constructorTearOff, parent);
 
+  @override
+  SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
+
   // TODO(johnniwinther,cstefantsova): Rename [actualOrigin] to avoid the
   //  confusion with patches.
   MemberBuilder? get actualOrigin {
diff --git a/pkg/front_end/lib/src/fasta/source/source_factory_builder.dart b/pkg/front_end/lib/src/fasta/source/source_factory_builder.dart
index 16072e5..edf0831 100644
--- a/pkg/front_end/lib/src/fasta/source/source_factory_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_factory_builder.dart
@@ -407,6 +407,11 @@
       inferrer.helper = library.loader.createBodyBuilderForOutlineExpression(
           library, classBuilder, this, classBuilder!.scope, fileUri);
       Builder? targetBuilder = redirectionTarget.target;
+      if (targetBuilder is SourceMemberBuilder) {
+        // Ensure that target has been built.
+        targetBuilder.buildOutlineExpressions(targetBuilder.library,
+            classHierarchy, delayedActionPerformers, synthesizedFunctionNodes);
+      }
       if (targetBuilder is FunctionBuilder) {
         target = targetBuilder.member;
       } else if (targetBuilder is DillMemberBuilder) {
@@ -457,14 +462,34 @@
           new RedirectingFactoryBody(target, typeArguments, function);
       function.body!.parent = function;
     }
-    if (_factoryTearOff != null &&
-        (target is Constructor || target is Procedure && target.isFactory)) {
-      synthesizedFunctionNodes.add(buildRedirectingFactoryTearOffBody(
-          _factoryTearOff!,
-          target!,
-          typeArguments ?? [],
-          _tearOffTypeParameters!,
-          library));
+    if (_factoryTearOff != null) {
+      Set<Procedure> seenTargets = {};
+      while (target is Procedure && target.isRedirectingFactory) {
+        if (!seenTargets.add(target)) {
+          // Cyclic dependency.
+          target = null;
+          break;
+        }
+        RedirectingFactoryBody body =
+            target.function.body as RedirectingFactoryBody;
+        if (typeArguments != null) {
+          Substitution substitution = Substitution.fromPairs(
+              target.function.typeParameters, typeArguments);
+          typeArguments =
+              body.typeArguments?.map(substitution.substituteType).toList();
+        } else {
+          typeArguments = body.typeArguments;
+        }
+        target = body.target;
+      }
+      if (target is Constructor || target is Procedure && target.isFactory) {
+        synthesizedFunctionNodes.add(buildRedirectingFactoryTearOffBody(
+            _factoryTearOff!,
+            target!,
+            typeArguments ?? [],
+            _tearOffTypeParameters!,
+            library));
+      }
     }
     if (isConst && isPatch) {
       _finishPatch();
diff --git a/pkg/front_end/lib/src/fasta/source/source_field_builder.dart b/pkg/front_end/lib/src/fasta/source/source_field_builder.dart
index 0f2b052..6735bb3 100644
--- a/pkg/front_end/lib/src/fasta/source/source_field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_field_builder.dart
@@ -283,9 +283,6 @@
   }
 
   @override
-  SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
-
-  @override
   Member get member => _fieldEncoding.field;
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/source/source_member_builder.dart b/pkg/front_end/lib/src/fasta/source/source_member_builder.dart
index f4cf938..9b8a08d 100644
--- a/pkg/front_end/lib/src/fasta/source/source_member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_member_builder.dart
@@ -25,6 +25,9 @@
 abstract class SourceMemberBuilder implements MemberBuilder {
   MemberDataForTesting? get dataForTesting;
 
+  @override
+  SourceLibraryBuilder get library;
+
   /// Builds the core AST structures for this member as needed for the outline.
   void buildMembers(
       SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f);
@@ -87,6 +90,9 @@
             retainDataForTesting ? new MemberDataForTesting() : null,
         super(parent, charOffset, fileUri);
 
+  @override
+  SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
+
   bool get isRedirectingGenerativeConstructor => false;
 
   @override
diff --git a/pkg/front_end/test/macro_application/data/tests/marker.options b/pkg/front_end/test/macro_application/data/tests/marker.options
deleted file mode 100644
index 578e904..0000000
--- a/pkg/front_end/test/macro_application/data/tests/marker.options
+++ /dev/null
@@ -1 +0,0 @@
-cfe=pkg/front_end/test/macro_application/macro_application_test.dart
diff --git a/pkg/front_end/test/macro_application/data/package_config.json b/pkg/front_end/test/macros/application/data/package_config.json
similarity index 69%
rename from pkg/front_end/test/macro_application/data/package_config.json
rename to pkg/front_end/test/macros/application/data/package_config.json
index fbfd870..2e8365d 100644
--- a/pkg/front_end/test/macro_application/data/package_config.json
+++ b/pkg/front_end/test/macros/application/data/package_config.json
@@ -7,12 +7,12 @@
     },
     {
       "name": "meta",
-      "rootUri": "../../../../meta/",
+      "rootUri": "../../../../../meta/",
       "packageUri": "lib/"
     },
     {
       "name": "_fe_analyzer_shared",
-      "rootUri": "../../../../_fe_analyzer_shared/lib/"
+      "rootUri": "../../../../../_fe_analyzer_shared/lib/"
     }
   ]
 }
\ No newline at end of file
diff --git a/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro.dart b/pkg/front_end/test/macros/application/data/pkgs/macro/lib/macro.dart
similarity index 100%
rename from pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro.dart
rename to pkg/front_end/test/macros/application/data/pkgs/macro/lib/macro.dart
diff --git a/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro1.dart b/pkg/front_end/test/macros/application/data/pkgs/macro/lib/macro1.dart
similarity index 100%
rename from pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro1.dart
rename to pkg/front_end/test/macros/application/data/pkgs/macro/lib/macro1.dart
diff --git a/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro2.dart b/pkg/front_end/test/macros/application/data/pkgs/macro/lib/macro2.dart
similarity index 100%
rename from pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro2.dart
rename to pkg/front_end/test/macros/application/data/pkgs/macro/lib/macro2.dart
diff --git a/pkg/front_end/test/macro_application/data/tests/declarations.dart b/pkg/front_end/test/macros/application/data/tests/declarations.dart
similarity index 100%
rename from pkg/front_end/test/macro_application/data/tests/declarations.dart
rename to pkg/front_end/test/macros/application/data/tests/declarations.dart
diff --git a/pkg/front_end/test/macro_application/data/tests/declarations.dart.expect b/pkg/front_end/test/macros/application/data/tests/declarations.dart.expect
similarity index 100%
rename from pkg/front_end/test/macro_application/data/tests/declarations.dart.expect
rename to pkg/front_end/test/macros/application/data/tests/declarations.dart.expect
diff --git a/pkg/front_end/test/macro_application/data/tests/layers.dart b/pkg/front_end/test/macros/application/data/tests/layers.dart
similarity index 100%
rename from pkg/front_end/test/macro_application/data/tests/layers.dart
rename to pkg/front_end/test/macros/application/data/tests/layers.dart
diff --git a/pkg/front_end/test/macro_application/data/tests/layers.dart.expect b/pkg/front_end/test/macros/application/data/tests/layers.dart.expect
similarity index 100%
rename from pkg/front_end/test/macro_application/data/tests/layers.dart.expect
rename to pkg/front_end/test/macros/application/data/tests/layers.dart.expect
diff --git a/pkg/front_end/test/macros/application/data/tests/marker.options b/pkg/front_end/test/macros/application/data/tests/marker.options
new file mode 100644
index 0000000..71e74a2
--- /dev/null
+++ b/pkg/front_end/test/macros/application/data/tests/marker.options
@@ -0,0 +1 @@
+cfe=pkg/front_end/test/macros/application/macro_application_test.dart
diff --git a/pkg/front_end/test/macro_application/data/tests/parameters.dart b/pkg/front_end/test/macros/application/data/tests/parameters.dart
similarity index 100%
rename from pkg/front_end/test/macro_application/data/tests/parameters.dart
rename to pkg/front_end/test/macros/application/data/tests/parameters.dart
diff --git a/pkg/front_end/test/macro_application/data/tests/parameters.dart.expect b/pkg/front_end/test/macros/application/data/tests/parameters.dart.expect
similarity index 100%
rename from pkg/front_end/test/macro_application/data/tests/parameters.dart.expect
rename to pkg/front_end/test/macros/application/data/tests/parameters.dart.expect
diff --git a/pkg/front_end/test/macro_application/data/tests/sequence.dart b/pkg/front_end/test/macros/application/data/tests/sequence.dart
similarity index 100%
rename from pkg/front_end/test/macro_application/data/tests/sequence.dart
rename to pkg/front_end/test/macros/application/data/tests/sequence.dart
diff --git a/pkg/front_end/test/macro_application/data/tests/sequence.dart.expect b/pkg/front_end/test/macros/application/data/tests/sequence.dart.expect
similarity index 100%
rename from pkg/front_end/test/macro_application/data/tests/sequence.dart.expect
rename to pkg/front_end/test/macros/application/data/tests/sequence.dart.expect
diff --git a/pkg/front_end/test/macro_application/data/tests/subtypes.dart b/pkg/front_end/test/macros/application/data/tests/subtypes.dart
similarity index 100%
rename from pkg/front_end/test/macro_application/data/tests/subtypes.dart
rename to pkg/front_end/test/macros/application/data/tests/subtypes.dart
diff --git a/pkg/front_end/test/macro_application/data/tests/subtypes.dart.expect b/pkg/front_end/test/macros/application/data/tests/subtypes.dart.expect
similarity index 100%
rename from pkg/front_end/test/macro_application/data/tests/subtypes.dart.expect
rename to pkg/front_end/test/macros/application/data/tests/subtypes.dart.expect
diff --git a/pkg/front_end/test/macro_application/data/tests/supertypes.dart b/pkg/front_end/test/macros/application/data/tests/supertypes.dart
similarity index 100%
rename from pkg/front_end/test/macro_application/data/tests/supertypes.dart
rename to pkg/front_end/test/macros/application/data/tests/supertypes.dart
diff --git a/pkg/front_end/test/macro_application/data/tests/supertypes.dart.expect b/pkg/front_end/test/macros/application/data/tests/supertypes.dart.expect
similarity index 100%
rename from pkg/front_end/test/macro_application/data/tests/supertypes.dart.expect
rename to pkg/front_end/test/macros/application/data/tests/supertypes.dart.expect
diff --git a/pkg/front_end/test/macro_application/data/tests/to_string.dart b/pkg/front_end/test/macros/application/data/tests/to_string.dart
similarity index 100%
rename from pkg/front_end/test/macro_application/data/tests/to_string.dart
rename to pkg/front_end/test/macros/application/data/tests/to_string.dart
diff --git a/pkg/front_end/test/macro_application/data/tests/to_string.dart.expect b/pkg/front_end/test/macros/application/data/tests/to_string.dart.expect
similarity index 100%
rename from pkg/front_end/test/macro_application/data/tests/to_string.dart.expect
rename to pkg/front_end/test/macros/application/data/tests/to_string.dart.expect
diff --git a/pkg/front_end/test/macro_application/data/tests/type_annotations.dart b/pkg/front_end/test/macros/application/data/tests/type_annotations.dart
similarity index 100%
rename from pkg/front_end/test/macro_application/data/tests/type_annotations.dart
rename to pkg/front_end/test/macros/application/data/tests/type_annotations.dart
diff --git a/pkg/front_end/test/macro_application/data/tests/type_annotations.dart.expect b/pkg/front_end/test/macros/application/data/tests/type_annotations.dart.expect
similarity index 100%
rename from pkg/front_end/test/macro_application/data/tests/type_annotations.dart.expect
rename to pkg/front_end/test/macros/application/data/tests/type_annotations.dart.expect
diff --git a/pkg/front_end/test/macro_application/data/tests/types.dart b/pkg/front_end/test/macros/application/data/tests/types.dart
similarity index 100%
rename from pkg/front_end/test/macro_application/data/tests/types.dart
rename to pkg/front_end/test/macros/application/data/tests/types.dart
diff --git a/pkg/front_end/test/macro_application/data/tests/types.dart.expect b/pkg/front_end/test/macros/application/data/tests/types.dart.expect
similarity index 100%
rename from pkg/front_end/test/macro_application/data/tests/types.dart.expect
rename to pkg/front_end/test/macros/application/data/tests/types.dart.expect
diff --git a/pkg/front_end/test/macro_application/macro_application_test.dart b/pkg/front_end/test/macros/application/macro_application_test.dart
similarity index 99%
rename from pkg/front_end/test/macro_application/macro_application_test.dart
rename to pkg/front_end/test/macros/application/macro_application_test.dart
index 3b988bb..ce74f2d 100644
--- a/pkg/front_end/test/macro_application/macro_application_test.dart
+++ b/pkg/front_end/test/macros/application/macro_application_test.dart
@@ -31,7 +31,7 @@
 import 'package:kernel/text/ast_to_text.dart';
 import 'package:vm/target/vm.dart';
 
-import '../utils/kernel_chain.dart';
+import '../../utils/kernel_chain.dart';
 
 Future<void> main(List<String> args) async {
   bool generateExpectations = args.contains('-g');
diff --git a/pkg/front_end/test/macros/data/tests/marker.options b/pkg/front_end/test/macros/data/tests/marker.options
deleted file mode 100644
index 8416ef5..0000000
--- a/pkg/front_end/test/macros/data/tests/marker.options
+++ /dev/null
@@ -1 +0,0 @@
-cfe=pkg/front_end/test/macros/macro_test.dart
diff --git a/pkg/front_end/test/macros/data/package_config.json b/pkg/front_end/test/macros/declaration/data/package_config.json
similarity index 81%
rename from pkg/front_end/test/macros/data/package_config.json
rename to pkg/front_end/test/macros/declaration/data/package_config.json
index f176d49..55ff011 100644
--- a/pkg/front_end/test/macros/data/package_config.json
+++ b/pkg/front_end/test/macros/declaration/data/package_config.json
@@ -11,7 +11,7 @@
     },
     {
       "name": "_fe_analyzer_shared",
-      "rootUri": "../../../../_fe_analyzer_shared/lib/"
+      "rootUri": "../../../../../_fe_analyzer_shared/lib/"
     }
   ]
 }
\ No newline at end of file
diff --git a/pkg/front_end/test/macros/data/pkgs/macro/lib/macro.dart b/pkg/front_end/test/macros/declaration/data/pkgs/macro/lib/macro.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/pkgs/macro/lib/macro.dart
rename to pkg/front_end/test/macros/declaration/data/pkgs/macro/lib/macro.dart
diff --git a/pkg/front_end/test/macros/data/pkgs/precompiled_macro/lib/precompiled_macro.dart b/pkg/front_end/test/macros/declaration/data/pkgs/precompiled_macro/lib/precompiled_macro.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/pkgs/precompiled_macro/lib/precompiled_macro.dart
rename to pkg/front_end/test/macros/declaration/data/pkgs/precompiled_macro/lib/precompiled_macro.dart
diff --git a/pkg/front_end/test/macros/data/pkgs/precompiled_macro/lib/src/macro_base.dart b/pkg/front_end/test/macros/declaration/data/pkgs/precompiled_macro/lib/src/macro_base.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/pkgs/precompiled_macro/lib/src/macro_base.dart
rename to pkg/front_end/test/macros/declaration/data/pkgs/precompiled_macro/lib/src/macro_base.dart
diff --git a/pkg/front_end/test/macros/data/tests/all_precompiled.dart b/pkg/front_end/test/macros/declaration/data/tests/all_precompiled.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/all_precompiled.dart
rename to pkg/front_end/test/macros/declaration/data/tests/all_precompiled.dart
diff --git a/pkg/front_end/test/macros/data/tests/applications.dart b/pkg/front_end/test/macros/declaration/data/tests/applications.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/applications.dart
rename to pkg/front_end/test/macros/declaration/data/tests/applications.dart
diff --git a/pkg/front_end/test/macros/data/tests/declare_macro.dart b/pkg/front_end/test/macros/declaration/data/tests/declare_macro.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/declare_macro.dart
rename to pkg/front_end/test/macros/declaration/data/tests/declare_macro.dart
diff --git a/pkg/front_end/test/macros/data/tests/declare_vs_apply/apply_lib.dart b/pkg/front_end/test/macros/declaration/data/tests/declare_vs_apply/apply_lib.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/declare_vs_apply/apply_lib.dart
rename to pkg/front_end/test/macros/declaration/data/tests/declare_vs_apply/apply_lib.dart
diff --git a/pkg/front_end/test/macros/data/tests/declare_vs_apply/apply_lib_dep.dart b/pkg/front_end/test/macros/declaration/data/tests/declare_vs_apply/apply_lib_dep.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/declare_vs_apply/apply_lib_dep.dart
rename to pkg/front_end/test/macros/declaration/data/tests/declare_vs_apply/apply_lib_dep.dart
diff --git a/pkg/front_end/test/macros/data/tests/declare_vs_apply/macro_lib.dart b/pkg/front_end/test/macros/declaration/data/tests/declare_vs_apply/macro_lib.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/declare_vs_apply/macro_lib.dart
rename to pkg/front_end/test/macros/declaration/data/tests/declare_vs_apply/macro_lib.dart
diff --git a/pkg/front_end/test/macros/data/tests/declare_vs_apply/macro_lib_dep.dart b/pkg/front_end/test/macros/declaration/data/tests/declare_vs_apply/macro_lib_dep.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/declare_vs_apply/macro_lib_dep.dart
rename to pkg/front_end/test/macros/declaration/data/tests/declare_vs_apply/macro_lib_dep.dart
diff --git a/pkg/front_end/test/macros/data/tests/declare_vs_apply/main.dart b/pkg/front_end/test/macros/declaration/data/tests/declare_vs_apply/main.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/declare_vs_apply/main.dart
rename to pkg/front_end/test/macros/declaration/data/tests/declare_vs_apply/main.dart
diff --git a/pkg/front_end/test/macros/data/tests/declare_vs_apply/main_lib_dep.dart b/pkg/front_end/test/macros/declaration/data/tests/declare_vs_apply/main_lib_dep.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/declare_vs_apply/main_lib_dep.dart
rename to pkg/front_end/test/macros/declaration/data/tests/declare_vs_apply/main_lib_dep.dart
diff --git a/pkg/front_end/test/macros/data/tests/direct_import.dart b/pkg/front_end/test/macros/declaration/data/tests/direct_import.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/direct_import.dart
rename to pkg/front_end/test/macros/declaration/data/tests/direct_import.dart
diff --git a/pkg/front_end/test/macros/data/tests/import_macro_builder.dart b/pkg/front_end/test/macros/declaration/data/tests/import_macro_builder.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/import_macro_builder.dart
rename to pkg/front_end/test/macros/declaration/data/tests/import_macro_builder.dart
diff --git a/pkg/front_end/test/macros/data/tests/import_macro_package.dart b/pkg/front_end/test/macros/declaration/data/tests/import_macro_package.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/import_macro_package.dart
rename to pkg/front_end/test/macros/declaration/data/tests/import_macro_package.dart
diff --git a/pkg/front_end/test/macros/data/tests/import_macro_source/macro_lib.dart b/pkg/front_end/test/macros/declaration/data/tests/import_macro_source/macro_lib.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/import_macro_source/macro_lib.dart
rename to pkg/front_end/test/macros/declaration/data/tests/import_macro_source/macro_lib.dart
diff --git a/pkg/front_end/test/macros/data/tests/import_macro_source/main.dart b/pkg/front_end/test/macros/declaration/data/tests/import_macro_source/main.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/import_macro_source/main.dart
rename to pkg/front_end/test/macros/declaration/data/tests/import_macro_source/main.dart
diff --git a/pkg/front_end/test/macros/data/tests/macro_declarations.dart b/pkg/front_end/test/macros/declaration/data/tests/macro_declarations.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/macro_declarations.dart
rename to pkg/front_end/test/macros/declaration/data/tests/macro_declarations.dart
diff --git a/pkg/front_end/test/macros/declaration/data/tests/marker.options b/pkg/front_end/test/macros/declaration/data/tests/marker.options
new file mode 100644
index 0000000..776355b
--- /dev/null
+++ b/pkg/front_end/test/macros/declaration/data/tests/marker.options
@@ -0,0 +1 @@
+cfe=pkg/front_end/test/macros/declaration/macro_declaration_test.dart
diff --git a/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib1.dart b/pkg/front_end/test/macros/declaration/data/tests/multiple_macros/macro_lib1.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib1.dart
rename to pkg/front_end/test/macros/declaration/data/tests/multiple_macros/macro_lib1.dart
diff --git a/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2a.dart b/pkg/front_end/test/macros/declaration/data/tests/multiple_macros/macro_lib2a.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2a.dart
rename to pkg/front_end/test/macros/declaration/data/tests/multiple_macros/macro_lib2a.dart
diff --git a/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2b.dart b/pkg/front_end/test/macros/declaration/data/tests/multiple_macros/macro_lib2b.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2b.dart
rename to pkg/front_end/test/macros/declaration/data/tests/multiple_macros/macro_lib2b.dart
diff --git a/pkg/front_end/test/macros/data/tests/multiple_macros/main.dart b/pkg/front_end/test/macros/declaration/data/tests/multiple_macros/main.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/multiple_macros/main.dart
rename to pkg/front_end/test/macros/declaration/data/tests/multiple_macros/main.dart
diff --git a/pkg/front_end/test/macros/data/tests/no_import.dart b/pkg/front_end/test/macros/declaration/data/tests/no_import.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/no_import.dart
rename to pkg/front_end/test/macros/declaration/data/tests/no_import.dart
diff --git a/pkg/front_end/test/macros/data/tests/precompiled.dart b/pkg/front_end/test/macros/declaration/data/tests/precompiled.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/precompiled.dart
rename to pkg/front_end/test/macros/declaration/data/tests/precompiled.dart
diff --git a/pkg/front_end/test/macros/data/tests/use_macro_package.dart b/pkg/front_end/test/macros/declaration/data/tests/use_macro_package.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/use_macro_package.dart
rename to pkg/front_end/test/macros/declaration/data/tests/use_macro_package.dart
diff --git a/pkg/front_end/test/macros/data/tests/use_macro_source/macro_lib.dart b/pkg/front_end/test/macros/declaration/data/tests/use_macro_source/macro_lib.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/use_macro_source/macro_lib.dart
rename to pkg/front_end/test/macros/declaration/data/tests/use_macro_source/macro_lib.dart
diff --git a/pkg/front_end/test/macros/data/tests/use_macro_source/main.dart b/pkg/front_end/test/macros/declaration/data/tests/use_macro_source/main.dart
similarity index 100%
rename from pkg/front_end/test/macros/data/tests/use_macro_source/main.dart
rename to pkg/front_end/test/macros/declaration/data/tests/use_macro_source/main.dart
diff --git a/pkg/front_end/test/macros/macro_test.dart b/pkg/front_end/test/macros/declaration/macro_declaration_test.dart
similarity index 100%
rename from pkg/front_end/test/macros/macro_test.dart
rename to pkg/front_end/test/macros/declaration/macro_declaration_test.dart
diff --git a/pkg/front_end/test/macro_api_test.dart b/pkg/front_end/test/macros/macro_api_test.dart
similarity index 92%
rename from pkg/front_end/test/macro_api_test.dart
rename to pkg/front_end/test/macros/macro_api_test.dart
index 70c3503..768d1d1 100644
--- a/pkg/front_end/test/macro_api_test.dart
+++ b/pkg/front_end/test/macros/macro_api_test.dart
@@ -28,7 +28,7 @@
     options.environmentDefines = {};
     options.explicitExperimentalFlags[ExperimentalFlag.macros] = true;
     options.packagesFileUri = Platform.script.resolve(
-        '../../_fe_analyzer_shared/test/macros/api/package_config.json');
+        '../../../_fe_analyzer_shared/test/macros/api/package_config.json');
     options.macroExecutorProvider = () async {
       return await isolatedExecutor.start(SerializationMode.byteDataServer);
     };
@@ -38,7 +38,7 @@
 
     InternalCompilerResult result = await kernelForProgramInternal(
         Platform.script.resolve(
-            '../../_fe_analyzer_shared/test/macros/api/api_test_data.dart'),
+            '../../../_fe_analyzer_shared/test/macros/api/api_test_data.dart'),
         options,
         retainDataForTesting: true) as InternalCompilerResult;
     Expect.isFalse(result.kernelTargetForTesting!.loader.hasSeenError);
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/pkg/front_end/testing.json b/pkg/front_end/testing.json
index c25a9d9..38037dc 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -466,8 +466,8 @@
       "test/extensions/data/",
       "test/id_testing/data/",
       "test/language_versioning/data/",
-      "test/macro_application/data/",
-      "test/macros/data/",
+      "test/macros/application/data/",
+      "test/macros/declaration/data/",
       "test/patching/data",
       "test/predicates/data",
       "test/static_types/data/",
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 bdb6626..79638a7 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 17
 PATCH 0
-PRERELEASE 187
+PRERELEASE 188
 PRERELEASE_PATCH 0
\ No newline at end of file