Version 2.17.0-83.0.dev

Merge commit '0fda2bfdaa50a2db7c0747e272b9aa7c688d1a82' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_raw_string.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_raw_string.dart
new file mode 100644
index 0000000..0ccd810
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_raw_string.dart
@@ -0,0 +1,54 @@
+// 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.
+
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/source/source_range.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+
+class ConvertToRawString extends CorrectionProducer {
+  @override
+  bool get canBeAppliedInBulk => true;
+
+  @override
+  bool get canBeAppliedToFile => true;
+
+  @override
+  FixKind get fixKind => DartFixKind.CONVERT_TO_RAW_STRING;
+
+  @override
+  FixKind get multiFixKind => DartFixKind.CONVERT_TO_RAW_STRING_MULTI;
+
+  @override
+  Future<void> compute(ChangeBuilder builder) async {
+    var stringLiteral = node;
+    if ((stringLiteral is! SimpleStringLiteral) || stringLiteral.isRaw) {
+      return;
+    }
+
+    var literal = stringLiteral.literal;
+    var deletionOffsets = <int>[];
+    for (var offset = stringLiteral.contentsOffset;
+        offset < stringLiteral.contentsEnd;
+        offset++) {
+      var character = literal.lexeme[offset - literal.offset];
+      if (character == r'\') {
+        deletionOffsets.add(offset);
+        offset++;
+      }
+    }
+
+    await builder.addDartFileEdit(file, (builder) {
+      builder.addSimpleInsertion(stringLiteral.offset, 'r');
+      for (var offset in deletionOffsets) {
+        builder.addDeletion(SourceRange(offset, 1));
+      }
+    });
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+  static ConvertToRawString newInstance() => ConvertToRawString();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index b4fb0b2..51f8992 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -508,6 +508,16 @@
     DartFixKindPriority.IN_FILE,
     "Convert to 'package:' imports everywhere in file",
   );
+  static const CONVERT_TO_RAW_STRING = FixKind(
+    'dart.fix.convert.toRawString',
+    DartFixKindPriority.DEFAULT,
+    'Convert to raw string',
+  );
+  static const CONVERT_TO_RAW_STRING_MULTI = FixKind(
+    'dart.fix.convert.toRawString.multi',
+    DartFixKindPriority.IN_FILE,
+    'Convert to raw strings everywhere in file',
+  );
   static const CONVERT_TO_RELATIVE_IMPORT = FixKind(
     'dart.fix.convert.toRelativeImport',
     DartFixKindPriority.DEFAULT,
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index bae5fc7..c3cdf0a 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -61,6 +61,7 @@
 import 'package:analysis_server/src/services/correction/dart/convert_to_null_aware_spread.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_on_type.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_package_import.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_to_raw_string.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_relative_import.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_set_literal.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_where_type.dart';
@@ -630,6 +631,9 @@
     LintNames.use_key_in_widget_constructors: [
       AddKeyToConstructors.newInstance,
     ],
+    LintNames.use_raw_strings: [
+      ConvertToRawString.newInstance,
+    ],
     LintNames.use_rethrow_when_possible: [
       UseRethrow.newInstance,
     ],
diff --git a/pkg/analysis_server/lib/src/services/linter/lint_names.dart b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
index 90e9fbe..c5df9b7 100644
--- a/pkg/analysis_server/lib/src/services/linter/lint_names.dart
+++ b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
@@ -142,5 +142,6 @@
       'use_function_type_syntax_for_parameters';
   static const String use_key_in_widget_constructors =
       'use_key_in_widget_constructors';
+  static const String use_raw_strings = 'use_raw_strings';
   static const String use_rethrow_when_possible = 'use_rethrow_when_possible';
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/convert_to_raw_string_test.dart b/pkg/analysis_server/test/src/services/correction/fix/convert_to_raw_string_test.dart
new file mode 100644
index 0000000..7a0a79e
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/convert_to_raw_string_test.dart
@@ -0,0 +1,74 @@
+// 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.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConvertToRawStringBulkTest);
+    defineReflectiveTests(ConvertToRawStringTest);
+  });
+}
+
+@reflectiveTest
+class ConvertToRawStringBulkTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.use_raw_strings;
+
+  Future<void> test_bulk() async {
+    await resolveTestCode(r"""
+var a = 'text \\ \$ \\\\' "\\" '${'\\'}';
+var b = '''
+text \\ \$ \\\\
+\\ \$ \\\\
+''';
+""");
+    await assertHasFix(r"""
+var a = r'text \ $ \\' r"\" '${r'\'}';
+var b = r'''
+text \ $ \\
+\ $ \\
+''';
+""");
+  }
+}
+
+@reflectiveTest
+class ConvertToRawStringTest extends FixProcessorLintTest {
+  @override
+  FixKind get kind => DartFixKind.CONVERT_TO_RAW_STRING;
+
+  @override
+  String get lintCode => LintNames.use_raw_strings;
+
+  Future<void> test_doubleQuotes() async {
+    await resolveTestCode(r'var a = "text \\ \$ \\\\";');
+    await assertHasFix(r'var a = r"text \ $ \\";');
+  }
+
+  Future<void> test_multiLines() async {
+    await resolveTestCode(r"""
+var a = '''
+text \\ \$ \\\\
+\\ \$ \\\\
+''';
+""");
+    await assertHasFix(r"""
+var a = r'''
+text \ $ \\
+\ $ \\
+''';
+""");
+  }
+
+  Future<void> test_singleQuotes() async {
+    await resolveTestCode(r"var a = 'text \\ \$ \\\\';");
+    await assertHasFix(r"var a = r'text \ $ \\';");
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
index 001e243..41969f1 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
@@ -75,6 +75,7 @@
 import 'convert_to_null_aware_test.dart' as convert_to_null_aware;
 import 'convert_to_on_type_test.dart' as convert_to_on_type;
 import 'convert_to_package_import_test.dart' as convert_to_package_import;
+import 'convert_to_raw_string_test.dart' as convert_to_raw_string;
 import 'convert_to_relative_import_test.dart' as convert_to_relative_import;
 import 'convert_to_set_literal_test.dart' as convert_to_set_literal;
 import 'convert_to_single_quoted_string_test.dart'
@@ -278,6 +279,7 @@
     convert_to_null_aware_spread.main();
     convert_to_on_type.main();
     convert_to_package_import.main();
+    convert_to_raw_string.main();
     convert_to_relative_import.main();
     convert_to_set_literal.main();
     convert_to_single_quoted_string.main();
diff --git a/pkg/front_end/lib/src/api_prototype/compiler_options.dart b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
index a8355e8..5a6fc48 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -9,7 +9,7 @@
     show DiagnosticMessage, DiagnosticMessageHandler;
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
 
-import 'package:kernel/ast.dart' show Version;
+import 'package:kernel/ast.dart' show Component, Version;
 
 import 'package:kernel/default_language_version.dart' as kernel
     show defaultLanguageVersion;
@@ -113,16 +113,32 @@
 
   /// Function that creates a [MacroExecutor] if supported.
   ///
-  /// This is an experimental feature.
+  /// This is part of the experimental macro feature.
   Future<MacroExecutor> Function() macroExecutorProvider =
       () async => throw 'Macro execution is not supported.';
 
   /// Map from [MacroClass] to [Uri] for the precompiled dill that contains
   /// the macro code.
   ///
-  /// This is an experimental feature.
+  /// This is part of the experimental macro feature.
   Map<MacroClass, Uri>? precompiledMacroUris;
 
+  /// The [Target] used for compiling macros.
+  ///
+  /// If `null`, macro declarations will not be precompiled, even when other
+  /// libraries depend on them.
+  /// This is part of the experimental macro feature.
+  Target? macroTarget;
+
+  /// Function that can create a [Uri] for the serialized result of a
+  /// [Component].
+  ///
+  /// This is used to turn a precompiled macro into a [Uri] that can be loaded
+  /// by the macro executor provided by [macroExecutorProvider].
+  ///
+  /// This is part of the experimental macro feature.
+  Future<Uri> Function(Component)? macroSerializer;
+
   /// Whether to generate code for the SDK.
   ///
   /// By default the front end resolves components using a prebuilt SDK summary.
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index e083a04..89836a7 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -1664,11 +1664,11 @@
     return annotation;
   }
 
-  Arguments parseArguments(Token token) {
+  ArgumentsImpl parseArguments(Token token) {
     Parser parser = new Parser(this,
         useImplicitCreationExpression: useImplicitCreationExpressionInCfe);
     token = parser.parseArgumentsRest(token);
-    Arguments arguments = pop() as Arguments;
+    ArgumentsImpl arguments = pop() as ArgumentsImpl;
     checkEmpty(token.charOffset);
     return arguments;
   }
@@ -1751,15 +1751,21 @@
       } else if (initializers.last is RedirectingInitializer) {
         RedirectingInitializer redirectingInitializer =
             initializers.last as RedirectingInitializer;
-        if (libraryBuilder.enableEnhancedEnumsInLibrary) {
-          redirectingInitializer.arguments.positional.insertAll(0, [
+        if (sourceClassBuilder is SourceEnumBuilder &&
+            libraryBuilder.enableEnhancedEnumsInLibrary) {
+          ArgumentsImpl arguments =
+              redirectingInitializer.arguments as ArgumentsImpl;
+          List<Expression> enumSyntheticArguments = [
             new VariableGetImpl(constructor.function.positionalParameters[0],
                 forNullGuardedAccess: false)
               ..parent = redirectingInitializer.arguments,
             new VariableGetImpl(constructor.function.positionalParameters[1],
                 forNullGuardedAccess: false)
               ..parent = redirectingInitializer.arguments
-          ]);
+          ];
+          arguments.positional.insertAll(0, enumSyntheticArguments);
+          arguments.argumentsOriginalOrder
+              ?.insertAll(0, enumSyntheticArguments);
         }
       }
 
@@ -1905,10 +1911,12 @@
       List<Expression> positional;
       List<NamedExpression> named;
       if (libraryBuilder.enableNamedArgumentsAnywhereInLibrary) {
-        positional =
-            new List<Expression>.filled(positionalCount, dummyExpression);
+        positional = new List<Expression>.filled(
+            positionalCount, dummyExpression,
+            growable: true);
         named = new List<NamedExpression>.filled(
-            arguments.length - positionalCount, dummyNamedExpression);
+            arguments.length - positionalCount, dummyNamedExpression,
+            growable: true);
         int positionalIndex = 0;
         int namedIndex = 0;
         for (int i = 0; i < arguments.length; i++) {
@@ -7337,11 +7345,13 @@
 
 abstract class EnsureLoaded {
   void ensureLoaded(Member? member);
+
   bool isLoaded(Member? member);
 }
 
 class Operator {
   final Token token;
+
   String get name => token.stringValue!;
 
   final int charOffset;
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index 88168b6..7d665b8 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -2810,7 +2810,9 @@
               templateConstEvalGetterNotFound
                   .withArguments(variable.name ?? ''));
     } else {
-      if (variable.parent is Let || _isFormalParameter(variable)) {
+      if (variable.parent is Let ||
+          variable.parent is LocalInitializer ||
+          _isFormalParameter(variable)) {
         return env.lookupVariable(node.variable) ??
             createEvaluationErrorConstant(
                 node,
@@ -4117,6 +4119,7 @@
   final EvaluationEnvironment? _parent;
 
   EvaluationEnvironment() : _parent = null;
+
   EvaluationEnvironment.withParent(this._parent);
 
   /// Whether the current environment is empty.
@@ -4214,18 +4217,21 @@
 /// Status that the statement returned a valid [Constant] value.
 class ReturnStatus extends ExecutionStatus {
   final Constant? value;
+
   ReturnStatus(this.value);
 }
 
 /// Status with an exception or error that the statement has thrown.
 class AbortStatus extends ExecutionStatus {
   final AbortConstant error;
+
   AbortStatus(this.error);
 }
 
 /// Status that the statement breaks out of an enclosing [LabeledStatement].
 class BreakStatus extends ExecutionStatus {
   final LabeledStatement target;
+
   BreakStatus(this.target);
 }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 534c8bf..d01d2d8 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -391,13 +391,38 @@
     builder.mixedInTypeBuilder = null;
   }
 
-  Future<BuildResult> buildOutlines({CanonicalName? nameRoot}) async {
-    if (loader.first == null) return new BuildResult();
-    return withCrashReporting<BuildResult>(() async {
+  bool _hasComputedNeededPrecompilations = false;
+
+  Future<NeededPrecompilations?> computeNeededPrecompilations() async {
+    assert(!_hasComputedNeededPrecompilations,
+        "Needed precompilations have already been computed.");
+    _hasComputedNeededPrecompilations = true;
+    if (loader.first == null) return null;
+    return withCrashReporting<NeededPrecompilations?>(() async {
       await loader.buildOutlines();
       loader.coreLibrary.becomeCoreLibrary();
       loader.resolveParts();
-      loader.computeMacroDeclarations();
+      return loader.computeMacroDeclarations();
+    }, () => loader.currentUriForCrashReporting);
+  }
+
+  Future<BuildResult> buildOutlines({CanonicalName? nameRoot}) async {
+    if (loader.first == null) return new BuildResult();
+    return withCrashReporting<BuildResult>(() async {
+      if (!_hasComputedNeededPrecompilations) {
+        NeededPrecompilations? neededPrecompilations =
+            await computeNeededPrecompilations();
+        // To support macros, the needed macro libraries must be compiled be
+        // they are applied. Any supporting pipeline must therefore call
+        // [computeNeededPrecompilations] before calling [buildOutlines] in
+        // order to perform any need compilation in advance.
+        //
+        // If [neededPrecompilations] is non-null here, it means that macro
+        // compilation was needed but not performed.
+        if (neededPrecompilations != null) {
+          throw new UnsupportedError('Macro precompilation is not supported.');
+        }
+      }
       loader.computeLibraryScopes();
       MacroApplications? macroApplications =
           await loader.computeMacroApplications();
@@ -1587,7 +1612,9 @@
 
 class BuildResult {
   final Component? component;
+  final NeededPrecompilations? neededPrecompilations;
   final MacroApplications? macroApplications;
 
-  BuildResult({this.component, this.macroApplications});
+  BuildResult(
+      {this.component, this.macroApplications, this.neededPrecompilations});
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/macro.dart b/pkg/front_end/lib/src/fasta/kernel/macro.dart
index 3ec39e6..995a036 100644
--- a/pkg/front_end/lib/src/fasta/kernel/macro.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/macro.dart
@@ -98,6 +98,16 @@
   Map<MemberBuilder, List<MacroApplication>> memberApplications = {};
 }
 
+/// Macro classes that need to be precompiled.
+class NeededPrecompilations {
+  /// Map from library uris to macro class names and the names of constructor
+  /// their constructors is returned for macro classes that need to be
+  /// precompiled.
+  final Map<Uri, Map<String, List<String>>> macroDeclarations;
+
+  NeededPrecompilations(this.macroDeclarations);
+}
+
 class MacroApplications {
   final macro.MacroExecutor _macroExecutor;
   final Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData;
diff --git a/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart b/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
index b6040af..b6a5104 100644
--- a/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
@@ -590,7 +590,7 @@
           MemberBuilder? constructorBuilder =
               constructorScopeBuilder[constructorName];
 
-          Arguments arguments;
+          ArgumentsImpl arguments;
           List<Expression> enumSyntheticArguments = <Expression>[
             new IntLiteral(index++),
             new StringLiteral(constant),
@@ -623,11 +623,13 @@
             bodyBuilder.performBacklogComputations(delayedActionPerformers);
 
             arguments.positional.insertAll(0, enumSyntheticArguments);
+            arguments.argumentsOriginalOrder
+                ?.insertAll(0, enumSyntheticArguments);
           } else {
             arguments = new ArgumentsImpl(enumSyntheticArguments);
           }
 
-          if (typeArguments != null && arguments is ArgumentsImpl) {
+          if (typeArguments != null) {
             ArgumentsImpl.setNonInferrableArgumentTypes(
                 arguments, typeArguments);
           } else if (cls.typeParameters.isNotEmpty) {
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index c46a77f..e90cf3d 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -1358,10 +1358,8 @@
   /// Computes which macro declarations that needs to be precompiled in order
   /// to support macro application during compilation.
   ///
-  /// If no macros need precompilation, `null` is returned. Otherwise a map
-  /// from library uris to macro class names and the names of constructor their
-  /// constructors is returned.
-  Map<Uri, Map<String, List<String>>>? computeMacroDeclarations() {
+  /// If no macros need precompilation, `null` is returned.
+  NeededPrecompilations? computeMacroDeclarations() {
     if (!enableMacros) return null;
 
     LibraryBuilder? macroLibraryBuilder = lookupLibraryBuilder(macroLibraryUri);
@@ -1526,7 +1524,7 @@
           // be more layers but we'll compute these at the next attempt at
           // compilation, when this layer has been precompiled.
           // TODO(johnniwinther): Use this to trigger a precompile step.
-          return neededPrecompilations;
+          return new NeededPrecompilations(neededPrecompilations);
         }
       }
     }
diff --git a/pkg/front_end/lib/src/kernel_generator_impl.dart b/pkg/front_end/lib/src/kernel_generator_impl.dart
index 948c756..990e8ed 100644
--- a/pkg/front_end/lib/src/kernel_generator_impl.dart
+++ b/pkg/front_end/lib/src/kernel_generator_impl.dart
@@ -5,37 +5,29 @@
 /// Defines the front-end API for converting source code to Dart Kernel objects.
 library front_end.kernel_generator_impl;
 
+import 'package:_fe_analyzer_shared/src/macros/bootstrap.dart';
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
-
 import 'package:kernel/ast.dart';
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/core_types.dart';
 
-import 'base/nnbd_mode.dart';
-
-import 'base/processed_options.dart' show ProcessedOptions;
-
-import 'fasta/compiler_context.dart' show CompilerContext;
-
-import 'fasta/crash.dart' show withCrashReporting;
-
-import 'fasta/dill/dill_target.dart' show DillTarget;
-
-import 'fasta/fasta_codes.dart' show LocatedMessage;
-
-import 'fasta/kernel/kernel_target.dart' show BuildResult, KernelTarget;
-
-import 'fasta/kernel/utils.dart' show printComponentText, serializeComponent;
-
-import 'fasta/kernel/verifier.dart' show verifyComponent;
-
-import 'fasta/source/source_loader.dart' show SourceLoader;
-
-import 'fasta/uri_translator.dart' show UriTranslator;
-
-import 'api_prototype/front_end.dart' show CompilerResult;
-
 import 'api_prototype/file_system.dart' show FileSystem;
+import 'api_prototype/front_end.dart' show CompilerOptions, CompilerResult;
+import 'api_prototype/kernel_generator.dart';
+import 'api_prototype/memory_file_system.dart';
+import 'base/nnbd_mode.dart';
+import 'base/processed_options.dart' show ProcessedOptions;
+import 'fasta/compiler_context.dart' show CompilerContext;
+import 'fasta/crash.dart' show withCrashReporting;
+import 'fasta/dill/dill_target.dart' show DillTarget;
+import 'fasta/fasta_codes.dart' show LocatedMessage;
+import 'fasta/hybrid_file_system.dart';
+import 'fasta/kernel/kernel_target.dart' show BuildResult, KernelTarget;
+import 'fasta/kernel/macro.dart';
+import 'fasta/kernel/utils.dart' show printComponentText, serializeComponent;
+import 'fasta/kernel/verifier.dart' show verifyComponent;
+import 'fasta/source/source_loader.dart' show SourceLoader;
+import 'fasta/uri_translator.dart' show UriTranslator;
 
 /// Implementation for the
 /// `package:front_end/src/api_prototype/kernel_generator.dart` and
@@ -69,6 +61,7 @@
 
   SourceLoader? sourceLoader;
   return withCrashReporting<CompilerResult>(() async {
+    // TODO(johnniwinther): How much can we reuse between iterations?
     UriTranslator uriTranslator = await options.getUriTranslator();
 
     DillTarget dillTarget =
@@ -96,98 +89,138 @@
         new KernelTarget(fs, false, dillTarget, uriTranslator);
     sourceLoader = kernelTarget.loader;
     kernelTarget.setEntryPoints(options.inputs);
-    BuildResult buildResult =
-        await kernelTarget.buildOutlines(nameRoot: nameRoot);
-    Component summaryComponent = buildResult.component!;
-    List<int>? summary = null;
-    if (buildSummary) {
-      if (options.verify) {
-        for (LocatedMessage error
-            in verifyComponent(summaryComponent, options.target)) {
-          options.report(error, Severity.error);
+    NeededPrecompilations? neededPrecompilations =
+        await kernelTarget.computeNeededPrecompilations();
+    if (neededPrecompilations != null) {
+      if (enableMacros) {
+        // TODO(johnniwinther): Avoid using [rawOptionsForTesting] to compute
+        // the compiler options for the precompilation.
+        if (options.rawOptionsForTesting.macroTarget != null) {
+          await _compileMacros(
+              neededPrecompilations, options.rawOptionsForTesting);
         }
+      } else {
+        throw new UnsupportedError('Macro precompilation is not supported');
       }
-      if (options.debugDump) {
-        printComponentText(summaryComponent,
-            libraryFilter: kernelTarget.isSourceLibraryForDebugging);
-      }
-
-      // Create the requested component ("truncating" or not).
-      //
-      // Note: we don't pass the library argument to the constructor to
-      // preserve the libraries parent pointer (it should continue to point
-      // to the component within KernelTarget).
-      Component trimmedSummaryComponent =
-          new Component(nameRoot: summaryComponent.root)
-            ..libraries.addAll(truncateSummary
-                ? kernelTarget.loader.libraries
-                : summaryComponent.libraries);
-      trimmedSummaryComponent.metadata.addAll(summaryComponent.metadata);
-      trimmedSummaryComponent.uriToSource.addAll(summaryComponent.uriToSource);
-
-      NonNullableByDefaultCompiledMode compiledMode =
-          NonNullableByDefaultCompiledMode.Weak;
-      switch (options.nnbdMode) {
-        case NnbdMode.Weak:
-          compiledMode = NonNullableByDefaultCompiledMode.Weak;
-          break;
-        case NnbdMode.Strong:
-          compiledMode = NonNullableByDefaultCompiledMode.Strong;
-          break;
-        case NnbdMode.Agnostic:
-          compiledMode = NonNullableByDefaultCompiledMode.Agnostic;
-          break;
-      }
-      if (kernelTarget.loader.hasInvalidNnbdModeLibrary) {
-        compiledMode = NonNullableByDefaultCompiledMode.Invalid;
-      }
-
-      trimmedSummaryComponent.setMainMethodAndMode(
-          trimmedSummaryComponent.mainMethodName, false, compiledMode);
-
-      // As documented, we only run outline transformations when we are building
-      // summaries without building a full component (at this time, that's
-      // the only need we have for these transformations).
-      if (!buildComponent) {
-        options.target.performOutlineTransformations(trimmedSummaryComponent);
-        options.ticker.logMs("Transformed outline");
-      }
-      // Don't include source (but do add it above to include importUris).
-      summary = serializeComponent(trimmedSummaryComponent,
-          includeSources: false, includeOffsets: includeOffsets);
-      options.ticker.logMs("Generated outline");
     }
-
-    Component? component;
-    if (buildComponent) {
-      buildResult = await kernelTarget.buildComponent(
-          macroApplications: buildResult.macroApplications,
-          verify: options.verify);
-      component = buildResult.component;
-      if (options.debugDump) {
-        printComponentText(component,
-            libraryFilter: kernelTarget.isSourceLibraryForDebugging);
-      }
-      options.ticker.logMs("Generated component");
-    }
-    // TODO(johnniwinther): Should we reuse the macro executor on subsequent
-    // compilations where possible?
-    buildResult.macroApplications?.close();
-
-    return new InternalCompilerResult(
-        summary: summary,
-        component: component,
-        sdkComponent: sdkSummary,
+    return _buildInternal(
+        options: options,
+        kernelTarget: kernelTarget,
+        nameRoot: nameRoot,
+        sdkSummary: sdkSummary,
         loadedComponents: loadedComponents,
-        classHierarchy:
-            includeHierarchyAndCoreTypes ? kernelTarget.loader.hierarchy : null,
-        coreTypes:
-            includeHierarchyAndCoreTypes ? kernelTarget.loader.coreTypes : null,
-        deps: new List<Uri>.of(CompilerContext.current.dependencies),
-        kernelTargetForTesting: retainDataForTesting ? kernelTarget : null);
+        buildSummary: buildSummary,
+        truncateSummary: truncateSummary,
+        buildComponent: buildComponent,
+        includeOffsets: includeOffsets,
+        includeHierarchyAndCoreTypes: includeHierarchyAndCoreTypes,
+        retainDataForTesting: retainDataForTesting);
   }, () => sourceLoader?.currentUriForCrashReporting ?? options.inputs.first);
 }
 
+Future<CompilerResult> _buildInternal(
+    {required ProcessedOptions options,
+    required KernelTarget kernelTarget,
+    required CanonicalName nameRoot,
+    required Component? sdkSummary,
+    required List<Component> loadedComponents,
+    required bool buildSummary,
+    required bool truncateSummary,
+    required bool buildComponent,
+    required bool includeOffsets,
+    required bool includeHierarchyAndCoreTypes,
+    required bool retainDataForTesting}) async {
+  BuildResult buildResult =
+      await kernelTarget.buildOutlines(nameRoot: nameRoot);
+  Component summaryComponent = buildResult.component!;
+  List<int>? summary = null;
+  if (buildSummary) {
+    if (options.verify) {
+      for (LocatedMessage error
+          in verifyComponent(summaryComponent, options.target)) {
+        options.report(error, Severity.error);
+      }
+    }
+    if (options.debugDump) {
+      printComponentText(summaryComponent,
+          libraryFilter: kernelTarget.isSourceLibraryForDebugging);
+    }
+
+    // Create the requested component ("truncating" or not).
+    //
+    // Note: we don't pass the library argument to the constructor to
+    // preserve the libraries parent pointer (it should continue to point
+    // to the component within KernelTarget).
+    Component trimmedSummaryComponent =
+        new Component(nameRoot: summaryComponent.root)
+          ..libraries.addAll(truncateSummary
+              ? kernelTarget.loader.libraries
+              : summaryComponent.libraries);
+    trimmedSummaryComponent.metadata.addAll(summaryComponent.metadata);
+    trimmedSummaryComponent.uriToSource.addAll(summaryComponent.uriToSource);
+
+    NonNullableByDefaultCompiledMode compiledMode =
+        NonNullableByDefaultCompiledMode.Weak;
+    switch (options.nnbdMode) {
+      case NnbdMode.Weak:
+        compiledMode = NonNullableByDefaultCompiledMode.Weak;
+        break;
+      case NnbdMode.Strong:
+        compiledMode = NonNullableByDefaultCompiledMode.Strong;
+        break;
+      case NnbdMode.Agnostic:
+        compiledMode = NonNullableByDefaultCompiledMode.Agnostic;
+        break;
+    }
+    if (kernelTarget.loader.hasInvalidNnbdModeLibrary) {
+      compiledMode = NonNullableByDefaultCompiledMode.Invalid;
+    }
+
+    trimmedSummaryComponent.setMainMethodAndMode(
+        trimmedSummaryComponent.mainMethodName, false, compiledMode);
+
+    // As documented, we only run outline transformations when we are building
+    // summaries without building a full component (at this time, that's
+    // the only need we have for these transformations).
+    if (!buildComponent) {
+      options.target.performOutlineTransformations(trimmedSummaryComponent);
+      options.ticker.logMs("Transformed outline");
+    }
+    // Don't include source (but do add it above to include importUris).
+    summary = serializeComponent(trimmedSummaryComponent,
+        includeSources: false, includeOffsets: includeOffsets);
+    options.ticker.logMs("Generated outline");
+  }
+
+  Component? component;
+  if (buildComponent) {
+    buildResult = await kernelTarget.buildComponent(
+        macroApplications: buildResult.macroApplications,
+        verify: options.verify);
+    component = buildResult.component;
+    if (options.debugDump) {
+      printComponentText(component,
+          libraryFilter: kernelTarget.isSourceLibraryForDebugging);
+    }
+    options.ticker.logMs("Generated component");
+  }
+  // TODO(johnniwinther): Should we reuse the macro executor on subsequent
+  // compilations where possible?
+  buildResult.macroApplications?.close();
+
+  return new InternalCompilerResult(
+      summary: summary,
+      component: component,
+      sdkComponent: sdkSummary,
+      loadedComponents: loadedComponents,
+      classHierarchy:
+          includeHierarchyAndCoreTypes ? kernelTarget.loader.hierarchy : null,
+      coreTypes:
+          includeHierarchyAndCoreTypes ? kernelTarget.loader.coreTypes : null,
+      deps: new List<Uri>.from(CompilerContext.current.dependencies),
+      kernelTargetForTesting: retainDataForTesting ? kernelTarget : null);
+}
+
 /// Result object of [generateKernel].
 class InternalCompilerResult implements CompilerResult {
   /// The generated summary bytes, if it was requested.
@@ -232,3 +265,52 @@
       this.coreTypes,
       this.kernelTargetForTesting});
 }
+
+/// A fake absolute directory used as the root of a memory-file system in the
+/// compilation below.
+Uri _defaultDir = Uri.parse('org-dartlang-macro:///a/b/c/');
+
+Future<void> _compileMacros(NeededPrecompilations neededPrecompilations,
+    CompilerOptions options) async {
+  assert(options.macroSerializer != null);
+  CompilerOptions precompilationOptions = new CompilerOptions();
+  precompilationOptions.target = options.macroTarget;
+  precompilationOptions.explicitExperimentalFlags =
+      options.explicitExperimentalFlags;
+  // TODO(johnniwinther): What is the right environment when it isn't passed
+  // by the caller? Dart2js calls the CFE without an environment, but it's
+  // macros likely need them.
+  precompilationOptions.environmentDefines = options.environmentDefines ?? {};
+  precompilationOptions.packagesFileUri = options.packagesFileUri;
+  precompilationOptions.precompiledMacroUris = options.precompiledMacroUris;
+  // TODO(johnniwinther): What if sdk root isn't set? How do we then get the
+  // right sdk?
+  precompilationOptions.sdkRoot = options.sdkRoot;
+  precompilationOptions.macroExecutorProvider = options.macroExecutorProvider;
+
+  Map<String, Map<String, List<String>>> macroDeclarations = {};
+  neededPrecompilations.macroDeclarations
+      .forEach((Uri uri, Map<String, List<String>> macroClasses) {
+    macroDeclarations[uri.toString()] = macroClasses;
+  });
+
+  Uri uri = _defaultDir.resolve('main.dart');
+  MemoryFileSystem fs = new MemoryFileSystem(_defaultDir);
+  fs
+      .entityForUri(uri)
+      .writeAsStringSync(bootstrapMacroIsolate(macroDeclarations));
+
+  precompilationOptions..fileSystem = new HybridFileSystem(fs);
+  CompilerResult? compilerResult =
+      await kernelForProgramInternal(uri, precompilationOptions);
+  Uri precompiledUri =
+      await options.macroSerializer!(compilerResult!.component!);
+  Map<MacroClass, Uri> precompiledMacroUris =
+      options.precompiledMacroUris ??= {};
+  neededPrecompilations.macroDeclarations
+      .forEach((Uri uri, Map<String, List<String>> macroClasses) {
+    for (String macroClass in macroClasses.keys) {
+      precompiledMacroUris[new MacroClass(uri, macroClass)] = precompiledUri;
+    }
+  });
+}
diff --git a/pkg/front_end/test/macro_application/macro_application_test.dart b/pkg/front_end/test/macro_application/macro_application_test.dart
index 42cbb6a..a32cae5 100644
--- a/pkg/front_end/test/macro_application/macro_application_test.dart
+++ b/pkg/front_end/test/macro_application/macro_application_test.dart
@@ -5,7 +5,6 @@
 import 'dart:io' show Directory, Platform;
 
 import 'package:_fe_analyzer_shared/src/macros/api.dart';
-import 'package:_fe_analyzer_shared/src/macros/bootstrap.dart';
 import 'package:_fe_analyzer_shared/src/macros/executor.dart';
 import 'package:_fe_analyzer_shared/src/macros/isolated_executor/isolated_executor.dart'
     as isolatedExecutor;
@@ -14,13 +13,11 @@
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:front_end/src/api_prototype/compiler_options.dart';
 import 'package:front_end/src/api_prototype/experimental_flags.dart';
-import 'package:front_end/src/api_prototype/kernel_generator.dart';
 import 'package:front_end/src/fasta/builder/field_builder.dart';
 import 'package:front_end/src/fasta/builder/member_builder.dart';
 import 'package:front_end/src/fasta/kernel/macro.dart';
 import 'package:front_end/src/fasta/kernel/utils.dart';
 import 'package:front_end/src/fasta/source/source_class_builder.dart';
-import 'package:front_end/src/testing/compiler_common.dart';
 import 'package:front_end/src/testing/id_extractor.dart';
 import 'package:front_end/src/testing/id_testing_helper.dart';
 import 'package:kernel/ast.dart' hide Arguments;
@@ -28,67 +25,32 @@
 import 'package:kernel/target/targets.dart';
 import 'package:vm/target/vm.dart';
 
-const Map<String, Map<String, List<String>>> macroDeclarations = {
-  'package:macro/macro.dart': {
-    'FunctionDefinitionMacro1': [''],
-    'FunctionDefinitionMacro2': [''],
-    'FunctionTypesMacro1': [''],
-    'FunctionDeclarationsMacro1': [''],
-    'FunctionDeclarationsMacro2': [''],
-    'MethodDeclarationsMacro1': [''],
-    'VariableDeclarationsMacro1': [''],
-    'FieldDeclarationsMacro1': [''],
-    'ClassDeclarationsMacro1': [''],
-    'ConstructorDeclarationsMacro1': [''],
-  }
-};
-
-Future<Uri> compileMacros(Directory directory) async {
-  CompilerOptions options = new CompilerOptions();
-  options.target = new VmTarget(new TargetFlags());
-  options.explicitExperimentalFlags[ExperimentalFlag.macros] = true;
-  options.environmentDefines = {};
-  options.packagesFileUri = Platform.script.resolve('data/package_config.json');
-
-  CompilerResult? compilerResult = await compileScript(
-      {'main.dart': bootstrapMacroIsolate(macroDeclarations)},
-      options: options, requireMain: false);
-  Uri uri = directory.absolute.uri.resolve('macros.dill');
-  await writeComponentToFile(compilerResult!.component!, uri);
-  return uri;
-}
-
 Future<void> main(List<String> args) async {
   enableMacros = true;
 
   Directory tempDirectory =
       await Directory.systemTemp.createTemp('macro_application');
-
-  Uri macrosUri = await compileMacros(tempDirectory);
-  Map<MacroClass, Uri> precompiledMacroUris = {};
-  macroDeclarations
-      .forEach((String macroUri, Map<String, List<String>> macroClasses) {
-    macroClasses.forEach((String macroClass, List<String> constructorNames) {
-      precompiledMacroUris[new MacroClass(Uri.parse(macroUri), macroClass)] =
-          macrosUri;
-    });
-  });
-
-  Directory dataDir =
-      new Directory.fromUri(Platform.script.resolve('data/tests'));
-  await runTests<String>(dataDir,
-      args: args,
-      createUriForFileName: createUriForFileName,
-      onFailure: onFailure,
-      runTest: runTestFor(const MacroDataComputer(),
-          [new MacroTestConfig(precompiledMacroUris)]),
-      preserveWhitespaceInAnnotations: true);
+  try {
+    Directory dataDir =
+        new Directory.fromUri(Platform.script.resolve('data/tests'));
+    await runTests<String>(dataDir,
+        args: args,
+        createUriForFileName: createUriForFileName,
+        onFailure: onFailure,
+        runTest: runTestFor(
+            const MacroDataComputer(), [new MacroTestConfig(tempDirectory)]),
+        preserveWhitespaceInAnnotations: true);
+  } finally {
+    await tempDirectory.delete(recursive: true);
+  }
 }
 
 class MacroTestConfig extends TestConfig {
-  final Map<MacroClass, Uri> precompiledMacroUris;
+  final Directory tempDirectory;
+  int precompiledCount = 0;
+  final Map<MacroClass, Uri> precompiledMacroUris = {};
 
-  MacroTestConfig(this.precompiledMacroUris)
+  MacroTestConfig(this.tempDirectory)
       : super(cfeMarker, 'cfe',
             explicitExperimentalFlags: {ExperimentalFlag.macros: true},
             packageConfigUri:
@@ -100,6 +62,13 @@
       return await isolatedExecutor.start();
     };
     options.precompiledMacroUris = precompiledMacroUris;
+    options.macroTarget = new VmTarget(new TargetFlags());
+    options.macroSerializer = (Component component) async {
+      Uri uri = tempDirectory.absolute.uri
+          .resolve('macros${precompiledCount++}.dill');
+      await writeComponentToFile(component, uri);
+      return uri;
+    };
   }
 }
 
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 5226583..7ddc634 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -901,6 +901,7 @@
 precompilations
 precompile
 precompiled
+precompiling
 preexisted
 preexisting
 prefixing
diff --git a/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart b/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart
new file mode 100644
index 0000000..47f596b
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart
@@ -0,0 +1,22 @@
+// 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.
+
+class C {
+  String log = "";
+
+  C(int x, int y, {int z = 42}) {
+    log = "x=$x, y=$y, z=$z";
+  }
+
+  C.named1(int x, int y, int z) : this(x, y, z: z);
+}
+
+main() {
+  expect("x=1, y=2, z=3", C(1, 2, z: 3).log);
+  expect("x=1, y=2, z=3", C.named1(1, 2, 3).log);
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.strong.expect
new file mode 100644
index 0000000..b3c69f0
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.strong.expect
@@ -0,0 +1,26 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field core::String log = "";
+  constructor •(core::int x, core::int y, {core::int z = #C1}) → self::C
+    : super core::Object::•() {
+    this.{self::C::log} = "x=${x}, y=${y}, z=${z}";
+  }
+  constructor named1(core::int x, core::int y, core::int z) → self::C
+    : this self::C::•(x, y, z: z)
+    ;
+}
+static method main() → dynamic {
+  self::expect("x=1, y=2, z=3", new self::C::•(1, 2, z: 3).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", new self::C::named1(1, 2, 3).{self::C::log}{core::String});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = 42
+}
diff --git a/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..b3c69f0
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.strong.transformed.expect
@@ -0,0 +1,26 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field core::String log = "";
+  constructor •(core::int x, core::int y, {core::int z = #C1}) → self::C
+    : super core::Object::•() {
+    this.{self::C::log} = "x=${x}, y=${y}, z=${z}";
+  }
+  constructor named1(core::int x, core::int y, core::int z) → self::C
+    : this self::C::•(x, y, z: z)
+    ;
+}
+static method main() → dynamic {
+  self::expect("x=1, y=2, z=3", new self::C::•(1, 2, z: 3).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", new self::C::named1(1, 2, 3).{self::C::log}{core::String});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = 42
+}
diff --git a/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.textual_outline.expect
new file mode 100644
index 0000000..88d946e
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.textual_outline.expect
@@ -0,0 +1,8 @@
+class C {
+  String log = "";
+  C(int x, int y, {int z = 42}) {}
+  C.named1(int x, int y, int z) : this(x, y, z: z);
+}
+
+main() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..055fa68
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.textual_outline_modelled.expect
@@ -0,0 +1,8 @@
+class C {
+  C(int x, int y, {int z = 42}) {}
+  C.named1(int x, int y, int z) : this(x, y, z: z);
+  String log = "";
+}
+
+expect(expected, actual) {}
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.weak.expect
new file mode 100644
index 0000000..b3c69f0
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.weak.expect
@@ -0,0 +1,26 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field core::String log = "";
+  constructor •(core::int x, core::int y, {core::int z = #C1}) → self::C
+    : super core::Object::•() {
+    this.{self::C::log} = "x=${x}, y=${y}, z=${z}";
+  }
+  constructor named1(core::int x, core::int y, core::int z) → self::C
+    : this self::C::•(x, y, z: z)
+    ;
+}
+static method main() → dynamic {
+  self::expect("x=1, y=2, z=3", new self::C::•(1, 2, z: 3).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", new self::C::named1(1, 2, 3).{self::C::log}{core::String});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = 42
+}
diff --git a/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.weak.modular.expect
new file mode 100644
index 0000000..b3c69f0
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.weak.modular.expect
@@ -0,0 +1,26 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field core::String log = "";
+  constructor •(core::int x, core::int y, {core::int z = #C1}) → self::C
+    : super core::Object::•() {
+    this.{self::C::log} = "x=${x}, y=${y}, z=${z}";
+  }
+  constructor named1(core::int x, core::int y, core::int z) → self::C
+    : this self::C::•(x, y, z: z)
+    ;
+}
+static method main() → dynamic {
+  self::expect("x=1, y=2, z=3", new self::C::•(1, 2, z: 3).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", new self::C::named1(1, 2, 3).{self::C::log}{core::String});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = 42
+}
diff --git a/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.weak.outline.expect
new file mode 100644
index 0000000..36d2092
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.weak.outline.expect
@@ -0,0 +1,15 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field core::String log;
+  constructor •(core::int x, core::int y, {core::int z = 42}) → self::C
+    ;
+  constructor named1(core::int x, core::int y, core::int z) → self::C
+    ;
+}
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.weak.transformed.expect
new file mode 100644
index 0000000..b3c69f0
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/class_redirecting_initializer.dart.weak.transformed.expect
@@ -0,0 +1,26 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field core::String log = "";
+  constructor •(core::int x, core::int y, {core::int z = #C1}) → self::C
+    : super core::Object::•() {
+    this.{self::C::log} = "x=${x}, y=${y}, z=${z}";
+  }
+  constructor named1(core::int x, core::int y, core::int z) → self::C
+    : this self::C::•(x, y, z: z)
+    ;
+}
+static method main() → dynamic {
+  self::expect("x=1, y=2, z=3", new self::C::•(1, 2, z: 3).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", new self::C::named1(1, 2, 3).{self::C::log}{core::String});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = 42
+}
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/folder.options b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/folder.options
new file mode 100644
index 0000000..c0139f7
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/folder.options
@@ -0,0 +1 @@
+--enable-experiment=enhanced-enums,named-arguments-anywhere
\ No newline at end of file
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart
new file mode 100644
index 0000000..73290e0
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart
@@ -0,0 +1,28 @@
+// 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.
+
+class C {
+  String log = "";
+
+  C(int x, int y, {int z = 42}) {
+    log = "x=$x, y=$y, z=$z";
+  }
+
+  C.named1(int x, int y, int z) : this(x, y, z: z);
+  C.named2(int x, int y, int z) : this(x, z: z, y);
+  C.named3(int x, int y, int z) : this(z: z, x, y);
+}
+
+main() {
+  expect("x=1, y=2, z=3", C(1, 2, z: 3).log);
+  expect("x=1, y=2, z=3", C(z: 3, 1, 2).log);
+  expect("x=1, y=2, z=3", C(1, z: 3, 2).log);
+  expect("x=1, y=2, z=3", C.named1(1, 2, 3).log);
+  expect("x=1, y=2, z=3", C.named2(1, 2, 3).log);
+  expect("x=1, y=2, z=3", C.named3(1, 2, 3).log);
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.strong.expect
new file mode 100644
index 0000000..af3e1a4
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.strong.expect
@@ -0,0 +1,36 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field core::String log = "";
+  constructor •(core::int x, core::int y, {core::int z = #C1}) → self::C
+    : super core::Object::•() {
+    this.{self::C::log} = "x=${x}, y=${y}, z=${z}";
+  }
+  constructor named1(core::int x, core::int y, core::int z) → self::C
+    : this self::C::•(x, y, z: z)
+    ;
+  constructor named2(core::int x, core::int y, core::int z) → self::C
+    : final core::int #t1 = x, final core::int #t2 = z, this self::C::•(#t1, y, z: #t2)
+    ;
+  constructor named3(core::int x, core::int y, core::int z) → self::C
+    : final core::int #t3 = z, this self::C::•(x, y, z: #t3)
+    ;
+}
+static method main() → dynamic {
+  self::expect("x=1, y=2, z=3", new self::C::•(1, 2, z: 3).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", (let final core::int #t4 = 3 in new self::C::•(1, 2, z: #t4)).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", (let final core::int #t5 = 1 in let final core::int #t6 = 3 in new self::C::•(#t5, 2, z: #t6)).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", new self::C::named1(1, 2, 3).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", new self::C::named2(1, 2, 3).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", new self::C::named3(1, 2, 3).{self::C::log}{core::String});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = 42
+}
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.strong.transformed.expect
new file mode 100644
index 0000000..233e403
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.strong.transformed.expect
@@ -0,0 +1,42 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field core::String log = "";
+  constructor •(core::int x, core::int y, {core::int z = #C1}) → self::C
+    : super core::Object::•() {
+    this.{self::C::log} = "x=${x}, y=${y}, z=${z}";
+  }
+  constructor named1(core::int x, core::int y, core::int z) → self::C
+    : this self::C::•(x, y, z: z)
+    ;
+  constructor named2(core::int x, core::int y, core::int z) → self::C
+    : final core::int #t1 = x, final core::int #t2 = z, this self::C::•(#t1, y, z: #t2)
+    ;
+  constructor named3(core::int x, core::int y, core::int z) → self::C
+    : final core::int #t3 = z, this self::C::•(x, y, z: #t3)
+    ;
+}
+static method main() → dynamic {
+  self::expect("x=1, y=2, z=3", new self::C::•(1, 2, z: 3).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", (let final core::int #t4 = 3 in new self::C::•(1, 2, z: #t4)).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", (let final core::int #t5 = 1 in let final core::int #t6 = 3 in new self::C::•(#t5, 2, z: #t6)).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", new self::C::named1(1, 2, 3).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", new self::C::named2(1, 2, 3).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", new self::C::named3(1, 2, 3).{self::C::log}{core::String});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = 42
+}
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///issue48276.dart:19:32 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///issue48276.dart:20:29 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///issue48276.dart:20:35 -> IntConstant(3)
+Extra constant evaluation: evaluated: 50, effectively constant: 3
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.textual_outline.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.textual_outline.expect
new file mode 100644
index 0000000..ecd5096
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.textual_outline.expect
@@ -0,0 +1,10 @@
+class C {
+  String log = "";
+  C(int x, int y, {int z = 42}) {}
+  C.named1(int x, int y, int z) : this(x, y, z: z);
+  C.named2(int x, int y, int z) : this(x, z: z, y);
+  C.named3(int x, int y, int z) : this(z: z, x, y);
+}
+
+main() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..6df982e
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.textual_outline_modelled.expect
@@ -0,0 +1,10 @@
+class C {
+  C(int x, int y, {int z = 42}) {}
+  C.named1(int x, int y, int z) : this(x, y, z: z);
+  C.named2(int x, int y, int z) : this(x, z: z, y);
+  C.named3(int x, int y, int z) : this(z: z, x, y);
+  String log = "";
+}
+
+expect(expected, actual) {}
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.weak.expect
new file mode 100644
index 0000000..af3e1a4
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.weak.expect
@@ -0,0 +1,36 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field core::String log = "";
+  constructor •(core::int x, core::int y, {core::int z = #C1}) → self::C
+    : super core::Object::•() {
+    this.{self::C::log} = "x=${x}, y=${y}, z=${z}";
+  }
+  constructor named1(core::int x, core::int y, core::int z) → self::C
+    : this self::C::•(x, y, z: z)
+    ;
+  constructor named2(core::int x, core::int y, core::int z) → self::C
+    : final core::int #t1 = x, final core::int #t2 = z, this self::C::•(#t1, y, z: #t2)
+    ;
+  constructor named3(core::int x, core::int y, core::int z) → self::C
+    : final core::int #t3 = z, this self::C::•(x, y, z: #t3)
+    ;
+}
+static method main() → dynamic {
+  self::expect("x=1, y=2, z=3", new self::C::•(1, 2, z: 3).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", (let final core::int #t4 = 3 in new self::C::•(1, 2, z: #t4)).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", (let final core::int #t5 = 1 in let final core::int #t6 = 3 in new self::C::•(#t5, 2, z: #t6)).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", new self::C::named1(1, 2, 3).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", new self::C::named2(1, 2, 3).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", new self::C::named3(1, 2, 3).{self::C::log}{core::String});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = 42
+}
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.weak.modular.expect
new file mode 100644
index 0000000..af3e1a4
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.weak.modular.expect
@@ -0,0 +1,36 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field core::String log = "";
+  constructor •(core::int x, core::int y, {core::int z = #C1}) → self::C
+    : super core::Object::•() {
+    this.{self::C::log} = "x=${x}, y=${y}, z=${z}";
+  }
+  constructor named1(core::int x, core::int y, core::int z) → self::C
+    : this self::C::•(x, y, z: z)
+    ;
+  constructor named2(core::int x, core::int y, core::int z) → self::C
+    : final core::int #t1 = x, final core::int #t2 = z, this self::C::•(#t1, y, z: #t2)
+    ;
+  constructor named3(core::int x, core::int y, core::int z) → self::C
+    : final core::int #t3 = z, this self::C::•(x, y, z: #t3)
+    ;
+}
+static method main() → dynamic {
+  self::expect("x=1, y=2, z=3", new self::C::•(1, 2, z: 3).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", (let final core::int #t4 = 3 in new self::C::•(1, 2, z: #t4)).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", (let final core::int #t5 = 1 in let final core::int #t6 = 3 in new self::C::•(#t5, 2, z: #t6)).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", new self::C::named1(1, 2, 3).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", new self::C::named2(1, 2, 3).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", new self::C::named3(1, 2, 3).{self::C::log}{core::String});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = 42
+}
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.weak.outline.expect
new file mode 100644
index 0000000..3724069
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.weak.outline.expect
@@ -0,0 +1,19 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field core::String log;
+  constructor •(core::int x, core::int y, {core::int z = 42}) → self::C
+    ;
+  constructor named1(core::int x, core::int y, core::int z) → self::C
+    ;
+  constructor named2(core::int x, core::int y, core::int z) → self::C
+    ;
+  constructor named3(core::int x, core::int y, core::int z) → self::C
+    ;
+}
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.weak.transformed.expect
new file mode 100644
index 0000000..233e403
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/issue48276.dart.weak.transformed.expect
@@ -0,0 +1,42 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field core::String log = "";
+  constructor •(core::int x, core::int y, {core::int z = #C1}) → self::C
+    : super core::Object::•() {
+    this.{self::C::log} = "x=${x}, y=${y}, z=${z}";
+  }
+  constructor named1(core::int x, core::int y, core::int z) → self::C
+    : this self::C::•(x, y, z: z)
+    ;
+  constructor named2(core::int x, core::int y, core::int z) → self::C
+    : final core::int #t1 = x, final core::int #t2 = z, this self::C::•(#t1, y, z: #t2)
+    ;
+  constructor named3(core::int x, core::int y, core::int z) → self::C
+    : final core::int #t3 = z, this self::C::•(x, y, z: #t3)
+    ;
+}
+static method main() → dynamic {
+  self::expect("x=1, y=2, z=3", new self::C::•(1, 2, z: 3).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", (let final core::int #t4 = 3 in new self::C::•(1, 2, z: #t4)).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", (let final core::int #t5 = 1 in let final core::int #t6 = 3 in new self::C::•(#t5, 2, z: #t6)).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", new self::C::named1(1, 2, 3).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", new self::C::named2(1, 2, 3).{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", new self::C::named3(1, 2, 3).{self::C::log}{core::String});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = 42
+}
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///issue48276.dart:19:32 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///issue48276.dart:20:29 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///issue48276.dart:20:35 -> IntConstant(3)
+Extra constant evaluation: evaluated: 50, effectively constant: 3
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart
new file mode 100644
index 0000000..e5f467c
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart
@@ -0,0 +1,35 @@
+// 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.
+
+enum C {
+  a(1, 2, z: 3),
+  b(z: 3, 1, 2),
+  c(1, z: 3, 2),
+  d.named1(1, 2, 3),
+  e.named2(1, 2, 3),
+  f.named3(1, 2, 3),
+  ;
+
+  final String log;
+
+  const C(int x, int y, {int z = 42})
+    : this.log = "x=$x, y=$y, z=$z";
+
+  const C.named1(int x, int y, int z) : this(x, y, z: z);
+  const C.named2(int x, int y, int z) : this(x, z: z, y);
+  const C.named3(int x, int y, int z) : this(z: z, x, y);
+}
+
+main() {
+  expect("x=1, y=2, z=3", C.a.log);
+  expect("x=1, y=2, z=3", C.b.log);
+  expect("x=1, y=2, z=3", C.c.log);
+  expect("x=1, y=2, z=3", C.d.log);
+  expect("x=1, y=2, z=3", C.e.log);
+  expect("x=1, y=2, z=3", C.f.log);
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.strong.expect
new file mode 100644
index 0000000..6b5605e
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.strong.expect
@@ -0,0 +1,74 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::C> values = #C20;
+  static const field self::C a = #C4;
+  static const field self::C b = #C7;
+  static const field self::C c = #C10;
+  static const field self::C d = #C13;
+  static const field self::C e = #C16;
+  static const field self::C f = #C19;
+  final field core::String log;
+  const constructor •(core::int index, core::String name, core::int x, core::int y, {core::int z = #C21}) → self::C
+    : self::C::log = "x=${x}, y=${y}, z=${z}", super core::_Enum::•(index, name)
+    ;
+  const constructor named1(core::int index, core::String name, core::int x, core::int y, core::int z) → self::C
+    : this self::C::•(index, name, x, y, z: z)
+    ;
+  const constructor named2(core::int index, core::String name, core::int x, core::int y, core::int z) → self::C
+    : final core::int #t1 = index, final core::String #t2 = name, final core::int #t3 = x, final core::int #t4 = z, this self::C::•(#t1, #t2, #t3, y, z: #t4)
+    ;
+  const constructor named3(core::int index, core::String name, core::int x, core::int y, core::int z) → self::C
+    : final core::int #t5 = index, final core::String #t6 = name, final core::int #t7 = z, this self::C::•(#t5, #t6, x, y, z: #t7)
+    ;
+  method toString() → core::String
+    return "C.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {
+  self::expect("x=1, y=2, z=3", #C4.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C7.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C10.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C13.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C16.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C19.{self::C::log}{core::String});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = "x=1, y=2, z=3"
+  #C2 = 0
+  #C3 = "a"
+  #C4 = self::C {log:#C1, index:#C2, _name:#C3}
+  #C5 = 1
+  #C6 = "b"
+  #C7 = self::C {log:#C1, index:#C5, _name:#C6}
+  #C8 = 2
+  #C9 = "c"
+  #C10 = self::C {log:#C1, index:#C8, _name:#C9}
+  #C11 = 3
+  #C12 = "d"
+  #C13 = self::C {log:#C1, index:#C11, _name:#C12}
+  #C14 = 4
+  #C15 = "e"
+  #C16 = self::C {log:#C1, index:#C14, _name:#C15}
+  #C17 = 5
+  #C18 = "f"
+  #C19 = self::C {log:#C1, index:#C17, _name:#C18}
+  #C20 = <self::C>[#C4, #C7, #C10, #C13, #C16, #C19]
+  #C21 = 42
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///redirecting_constructor.dart:
+- C. (from org-dartlang-testcase:///redirecting_constructor.dart:16:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- C.named1 (from org-dartlang-testcase:///redirecting_constructor.dart:19:9)
+- C.named2 (from org-dartlang-testcase:///redirecting_constructor.dart:20:9)
+- C.named3 (from org-dartlang-testcase:///redirecting_constructor.dart:21:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.strong.transformed.expect
new file mode 100644
index 0000000..6b5605e
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.strong.transformed.expect
@@ -0,0 +1,74 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::C> values = #C20;
+  static const field self::C a = #C4;
+  static const field self::C b = #C7;
+  static const field self::C c = #C10;
+  static const field self::C d = #C13;
+  static const field self::C e = #C16;
+  static const field self::C f = #C19;
+  final field core::String log;
+  const constructor •(core::int index, core::String name, core::int x, core::int y, {core::int z = #C21}) → self::C
+    : self::C::log = "x=${x}, y=${y}, z=${z}", super core::_Enum::•(index, name)
+    ;
+  const constructor named1(core::int index, core::String name, core::int x, core::int y, core::int z) → self::C
+    : this self::C::•(index, name, x, y, z: z)
+    ;
+  const constructor named2(core::int index, core::String name, core::int x, core::int y, core::int z) → self::C
+    : final core::int #t1 = index, final core::String #t2 = name, final core::int #t3 = x, final core::int #t4 = z, this self::C::•(#t1, #t2, #t3, y, z: #t4)
+    ;
+  const constructor named3(core::int index, core::String name, core::int x, core::int y, core::int z) → self::C
+    : final core::int #t5 = index, final core::String #t6 = name, final core::int #t7 = z, this self::C::•(#t5, #t6, x, y, z: #t7)
+    ;
+  method toString() → core::String
+    return "C.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {
+  self::expect("x=1, y=2, z=3", #C4.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C7.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C10.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C13.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C16.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C19.{self::C::log}{core::String});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = "x=1, y=2, z=3"
+  #C2 = 0
+  #C3 = "a"
+  #C4 = self::C {log:#C1, index:#C2, _name:#C3}
+  #C5 = 1
+  #C6 = "b"
+  #C7 = self::C {log:#C1, index:#C5, _name:#C6}
+  #C8 = 2
+  #C9 = "c"
+  #C10 = self::C {log:#C1, index:#C8, _name:#C9}
+  #C11 = 3
+  #C12 = "d"
+  #C13 = self::C {log:#C1, index:#C11, _name:#C12}
+  #C14 = 4
+  #C15 = "e"
+  #C16 = self::C {log:#C1, index:#C14, _name:#C15}
+  #C17 = 5
+  #C18 = "f"
+  #C19 = self::C {log:#C1, index:#C17, _name:#C18}
+  #C20 = <self::C>[#C4, #C7, #C10, #C13, #C16, #C19]
+  #C21 = 42
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///redirecting_constructor.dart:
+- C. (from org-dartlang-testcase:///redirecting_constructor.dart:16:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- C.named1 (from org-dartlang-testcase:///redirecting_constructor.dart:19:9)
+- C.named2 (from org-dartlang-testcase:///redirecting_constructor.dart:20:9)
+- C.named3 (from org-dartlang-testcase:///redirecting_constructor.dart:21:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.textual_outline.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.textual_outline.expect
new file mode 100644
index 0000000..03be650
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+enum C { a(1, 2, z: 3), b(z: 3, 1, 2), c(1, z: 3, 2), d.named1(1, 2, 3), e.named2(1, 2, 3), f.named3(1, 2, 3), ; final String log; const C(int x, int y, {int z = 42}) : this.log = "x=$x, y=$y, z=$z"; const C.named1(int x, int y, int z) : this(x, y, z: z); const C.named2(int x, int y, int z) : this(x, z: z, y); const C.named3(int x, int y, int z) : this(z: z, x, y); }
+main() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.weak.expect
new file mode 100644
index 0000000..e8052bd
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.weak.expect
@@ -0,0 +1,74 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::C> values = #C20;
+  static const field self::C a = #C4;
+  static const field self::C b = #C7;
+  static const field self::C c = #C10;
+  static const field self::C d = #C13;
+  static const field self::C e = #C16;
+  static const field self::C f = #C19;
+  final field core::String log;
+  const constructor •(core::int index, core::String name, core::int x, core::int y, {core::int z = #C21}) → self::C
+    : self::C::log = "x=${x}, y=${y}, z=${z}", super core::_Enum::•(index, name)
+    ;
+  const constructor named1(core::int index, core::String name, core::int x, core::int y, core::int z) → self::C
+    : this self::C::•(index, name, x, y, z: z)
+    ;
+  const constructor named2(core::int index, core::String name, core::int x, core::int y, core::int z) → self::C
+    : final core::int #t1 = index, final core::String #t2 = name, final core::int #t3 = x, final core::int #t4 = z, this self::C::•(#t1, #t2, #t3, y, z: #t4)
+    ;
+  const constructor named3(core::int index, core::String name, core::int x, core::int y, core::int z) → self::C
+    : final core::int #t5 = index, final core::String #t6 = name, final core::int #t7 = z, this self::C::•(#t5, #t6, x, y, z: #t7)
+    ;
+  method toString() → core::String
+    return "C.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {
+  self::expect("x=1, y=2, z=3", #C4.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C7.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C10.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C13.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C16.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C19.{self::C::log}{core::String});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = "x=1, y=2, z=3"
+  #C2 = 0
+  #C3 = "a"
+  #C4 = self::C {log:#C1, index:#C2, _name:#C3}
+  #C5 = 1
+  #C6 = "b"
+  #C7 = self::C {log:#C1, index:#C5, _name:#C6}
+  #C8 = 2
+  #C9 = "c"
+  #C10 = self::C {log:#C1, index:#C8, _name:#C9}
+  #C11 = 3
+  #C12 = "d"
+  #C13 = self::C {log:#C1, index:#C11, _name:#C12}
+  #C14 = 4
+  #C15 = "e"
+  #C16 = self::C {log:#C1, index:#C14, _name:#C15}
+  #C17 = 5
+  #C18 = "f"
+  #C19 = self::C {log:#C1, index:#C17, _name:#C18}
+  #C20 = <self::C*>[#C4, #C7, #C10, #C13, #C16, #C19]
+  #C21 = 42
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///redirecting_constructor.dart:
+- C. (from org-dartlang-testcase:///redirecting_constructor.dart:16:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- C.named1 (from org-dartlang-testcase:///redirecting_constructor.dart:19:9)
+- C.named2 (from org-dartlang-testcase:///redirecting_constructor.dart:20:9)
+- C.named3 (from org-dartlang-testcase:///redirecting_constructor.dart:21:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.weak.modular.expect
new file mode 100644
index 0000000..e8052bd
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.weak.modular.expect
@@ -0,0 +1,74 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::C> values = #C20;
+  static const field self::C a = #C4;
+  static const field self::C b = #C7;
+  static const field self::C c = #C10;
+  static const field self::C d = #C13;
+  static const field self::C e = #C16;
+  static const field self::C f = #C19;
+  final field core::String log;
+  const constructor •(core::int index, core::String name, core::int x, core::int y, {core::int z = #C21}) → self::C
+    : self::C::log = "x=${x}, y=${y}, z=${z}", super core::_Enum::•(index, name)
+    ;
+  const constructor named1(core::int index, core::String name, core::int x, core::int y, core::int z) → self::C
+    : this self::C::•(index, name, x, y, z: z)
+    ;
+  const constructor named2(core::int index, core::String name, core::int x, core::int y, core::int z) → self::C
+    : final core::int #t1 = index, final core::String #t2 = name, final core::int #t3 = x, final core::int #t4 = z, this self::C::•(#t1, #t2, #t3, y, z: #t4)
+    ;
+  const constructor named3(core::int index, core::String name, core::int x, core::int y, core::int z) → self::C
+    : final core::int #t5 = index, final core::String #t6 = name, final core::int #t7 = z, this self::C::•(#t5, #t6, x, y, z: #t7)
+    ;
+  method toString() → core::String
+    return "C.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {
+  self::expect("x=1, y=2, z=3", #C4.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C7.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C10.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C13.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C16.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C19.{self::C::log}{core::String});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = "x=1, y=2, z=3"
+  #C2 = 0
+  #C3 = "a"
+  #C4 = self::C {log:#C1, index:#C2, _name:#C3}
+  #C5 = 1
+  #C6 = "b"
+  #C7 = self::C {log:#C1, index:#C5, _name:#C6}
+  #C8 = 2
+  #C9 = "c"
+  #C10 = self::C {log:#C1, index:#C8, _name:#C9}
+  #C11 = 3
+  #C12 = "d"
+  #C13 = self::C {log:#C1, index:#C11, _name:#C12}
+  #C14 = 4
+  #C15 = "e"
+  #C16 = self::C {log:#C1, index:#C14, _name:#C15}
+  #C17 = 5
+  #C18 = "f"
+  #C19 = self::C {log:#C1, index:#C17, _name:#C18}
+  #C20 = <self::C*>[#C4, #C7, #C10, #C13, #C16, #C19]
+  #C21 = 42
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///redirecting_constructor.dart:
+- C. (from org-dartlang-testcase:///redirecting_constructor.dart:16:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- C.named1 (from org-dartlang-testcase:///redirecting_constructor.dart:19:9)
+- C.named2 (from org-dartlang-testcase:///redirecting_constructor.dart:20:9)
+- C.named3 (from org-dartlang-testcase:///redirecting_constructor.dart:21:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.weak.outline.expect
new file mode 100644
index 0000000..4a9962c
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.weak.outline.expect
@@ -0,0 +1,43 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::C> values = const <self::C>[self::C::a, self::C::b, self::C::c, self::C::d, self::C::e, self::C::f];
+  static const field self::C a = const self::C::•(0, "a", 1, 2, z: 3);
+  static const field self::C b = let final core::int #t1 = 1 in let final core::String #t2 = "b" in let final core::int #t3 = 3 in const self::C::•(#t1, #t2, 1, 2, z: #t3);
+  static const field self::C c = let final core::int #t4 = 2 in let final core::String #t5 = "c" in let final core::int #t6 = 1 in let final core::int #t7 = 3 in const self::C::•(#t4, #t5, #t6, 2, z: #t7);
+  static const field self::C d = const self::C::named1(3, "d", 1, 2, 3);
+  static const field self::C e = const self::C::named2(4, "e", 1, 2, 3);
+  static const field self::C f = const self::C::named3(5, "f", 1, 2, 3);
+  final field core::String log;
+  const constructor •(core::int index, core::String name, core::int x, core::int y, {core::int z = 42}) → self::C
+    : self::C::log = "x=${x}, y=${y}, z=${z}", super core::_Enum::•(index, name)
+    ;
+  const constructor named1(core::int index, core::String name, core::int x, core::int y, core::int z) → self::C
+    : this self::C::•(index, name, x, y, z: z)
+    ;
+  const constructor named2(core::int index, core::String name, core::int x, core::int y, core::int z) → self::C
+    : final core::int #t8 = index, final core::String #t9 = name, final core::int #t10 = x, final core::int #t11 = z, this self::C::•(#t8, #t9, #t10, y, z: #t11)
+    ;
+  const constructor named3(core::int index, core::String name, core::int x, core::int y, core::int z) → self::C
+    : final core::int #t12 = index, final core::String #t13 = name, final core::int #t14 = z, this self::C::•(#t12, #t13, x, y, z: #t14)
+    ;
+  method toString() → core::String
+    return "C.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///redirecting_constructor.dart:5:6 -> ListConstant(const <C*>[const C{C.log: "x=1, y=2, z=3", _Enum.index: 0, _Enum._name: "a"}, const C{C.log: "x=1, y=2, z=3", _Enum.index: 1, _Enum._name: "b"}, const C{C.log: "x=1, y=2, z=3", _Enum.index: 2, _Enum._name: "c"}, const C{C.log: "x=1, y=2, z=3", _Enum.index: 3, _Enum._name: "d"}, const C{C.log: "x=1, y=2, z=3", _Enum.index: 4, _Enum._name: "e"}, const C{C.log: "x=1, y=2, z=3", _Enum.index: 5, _Enum._name: "f"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///redirecting_constructor.dart:6:3 -> InstanceConstant(const C{C.log: "x=1, y=2, z=3", _Enum.index: 0, _Enum._name: "a"})
+Evaluated: Let @ org-dartlang-testcase:///redirecting_constructor.dart:7:3 -> InstanceConstant(const C{C.log: "x=1, y=2, z=3", _Enum.index: 1, _Enum._name: "b"})
+Evaluated: Let @ org-dartlang-testcase:///redirecting_constructor.dart:8:3 -> InstanceConstant(const C{C.log: "x=1, y=2, z=3", _Enum.index: 2, _Enum._name: "c"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///redirecting_constructor.dart:9:3 -> InstanceConstant(const C{C.log: "x=1, y=2, z=3", _Enum.index: 3, _Enum._name: "d"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///redirecting_constructor.dart:10:3 -> InstanceConstant(const C{C.log: "x=1, y=2, z=3", _Enum.index: 4, _Enum._name: "e"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///redirecting_constructor.dart:11:3 -> InstanceConstant(const C{C.log: "x=1, y=2, z=3", _Enum.index: 5, _Enum._name: "f"})
+Extra constant evaluation: evaluated: 38, effectively constant: 7
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.weak.transformed.expect
new file mode 100644
index 0000000..e8052bd
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.weak.transformed.expect
@@ -0,0 +1,74 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::C> values = #C20;
+  static const field self::C a = #C4;
+  static const field self::C b = #C7;
+  static const field self::C c = #C10;
+  static const field self::C d = #C13;
+  static const field self::C e = #C16;
+  static const field self::C f = #C19;
+  final field core::String log;
+  const constructor •(core::int index, core::String name, core::int x, core::int y, {core::int z = #C21}) → self::C
+    : self::C::log = "x=${x}, y=${y}, z=${z}", super core::_Enum::•(index, name)
+    ;
+  const constructor named1(core::int index, core::String name, core::int x, core::int y, core::int z) → self::C
+    : this self::C::•(index, name, x, y, z: z)
+    ;
+  const constructor named2(core::int index, core::String name, core::int x, core::int y, core::int z) → self::C
+    : final core::int #t1 = index, final core::String #t2 = name, final core::int #t3 = x, final core::int #t4 = z, this self::C::•(#t1, #t2, #t3, y, z: #t4)
+    ;
+  const constructor named3(core::int index, core::String name, core::int x, core::int y, core::int z) → self::C
+    : final core::int #t5 = index, final core::String #t6 = name, final core::int #t7 = z, this self::C::•(#t5, #t6, x, y, z: #t7)
+    ;
+  method toString() → core::String
+    return "C.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {
+  self::expect("x=1, y=2, z=3", #C4.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C7.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C10.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C13.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C16.{self::C::log}{core::String});
+  self::expect("x=1, y=2, z=3", #C19.{self::C::log}{core::String});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = "x=1, y=2, z=3"
+  #C2 = 0
+  #C3 = "a"
+  #C4 = self::C {log:#C1, index:#C2, _name:#C3}
+  #C5 = 1
+  #C6 = "b"
+  #C7 = self::C {log:#C1, index:#C5, _name:#C6}
+  #C8 = 2
+  #C9 = "c"
+  #C10 = self::C {log:#C1, index:#C8, _name:#C9}
+  #C11 = 3
+  #C12 = "d"
+  #C13 = self::C {log:#C1, index:#C11, _name:#C12}
+  #C14 = 4
+  #C15 = "e"
+  #C16 = self::C {log:#C1, index:#C14, _name:#C15}
+  #C17 = 5
+  #C18 = "f"
+  #C19 = self::C {log:#C1, index:#C17, _name:#C18}
+  #C20 = <self::C*>[#C4, #C7, #C10, #C13, #C16, #C19]
+  #C21 = 42
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///redirecting_constructor.dart:
+- C. (from org-dartlang-testcase:///redirecting_constructor.dart:16:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- C.named1 (from org-dartlang-testcase:///redirecting_constructor.dart:19:9)
+- C.named2 (from org-dartlang-testcase:///redirecting_constructor.dart:20:9)
+- C.named3 (from org-dartlang-testcase:///redirecting_constructor.dart:21:9)
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 5a838fa..1dbaebd 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -9,6 +9,8 @@
 constructor_tearoffs/call_instantiation: TypeCheckError
 constructor_tearoffs/lowering/invalid_redirect: VerificationError
 enhanced_enums/simple_mixins: RuntimeError
+enhanced_enums/named_arguments_anywhere/issue48276: TextSerializationFailure # Issue 47524.
+enhanced_enums/named_arguments_anywhere/redirecting_constructor: TextSerializationFailure # Issue 47524.
 extension_types/access_setter_as_getter: ExpectationFileMismatchSerialized # Expected.
 extension_types/call_not_get: ExpectationFileMismatchSerialized # Expected.
 extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index 5c09d8e..8c015e4 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -38,6 +38,7 @@
 enhanced_enums/malformed_constructors: FormatterCrash
 enhanced_enums/members: FormatterCrash
 enhanced_enums/named_arguments: FormatterCrash
+enhanced_enums/named_arguments_anywhere/redirecting_constructor: FormatterCrash
 enhanced_enums/qualified_names_with_no_type_arguments: FormatterCrash
 enhanced_enums/redirecting_initializers: FormatterCrash
 enhanced_enums/simple_fields: FormatterCrash
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
index 1443d95..7a6dc01 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
@@ -22,6 +22,6 @@
   synthetic constructor •() → self::Class
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3384,getterSelectorId:3385]  method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::Enum e) → core::int
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3396,getterSelectorId:3397]  method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::Enum e) → core::int
     return [@vm.inferred-type.metadata=!] e.{core::_Enum::index}{core::int};
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
index c16c8ac..5bebd25 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
@@ -51,6 +51,6 @@
   synthetic constructor •() → self::ConstClass
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3388,getterSelectorId:3389]  method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::ConstEnum e) → core::int
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3400,getterSelectorId:3401]  method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::ConstEnum e) → core::int
     return [@vm.inferred-type.metadata=!] e.{core::_Enum::index}{core::int};
 }
diff --git a/runtime/vm/compiler/backend/linearscan.cc b/runtime/vm/compiler/backend/linearscan.cc
index c6767a5..19191d1 100644
--- a/runtime/vm/compiler/backend/linearscan.cc
+++ b/runtime/vm/compiler/backend/linearscan.cc
@@ -321,6 +321,16 @@
 }
 
 void LiveRange::AddSafepoint(intptr_t pos, LocationSummary* locs) {
+  if (spill_slot().IsConstant() &&
+      (locs->always_calls() && !locs->callee_safe_call())) {
+    // Constants have pseudo spill slot assigned to them from
+    // the very beginning. This means that we don't need to associate
+    // "always_calls" safepoints with these ranges, because they will never
+    // be spilled. We still need to associate slow-path safepoints because
+    // a value might be allocated to a register across a slow-path call.
+    return;
+  }
+
   ASSERT(IsInstructionStartPosition(pos));
   SafepointPosition* safepoint =
       new SafepointPosition(ToInstructionEnd(pos), locs);
diff --git a/sdk/lib/_internal/vm/lib/compact_hash.dart b/sdk/lib/_internal/vm/lib/compact_hash.dart
index f2b6fc0..6ed0c80 100644
--- a/sdk/lib/_internal/vm/lib/compact_hash.dart
+++ b/sdk/lib/_internal/vm/lib/compact_hash.dart
@@ -325,6 +325,11 @@
     // Publish new index, uses store release semantics.
     _index = newIndex;
   }
+
+  Iterable<K> get keys =>
+      new _CompactIterableImmutable<K>(this, _data, _usedData, -2, 2);
+  Iterable<V> get values =>
+      new _CompactIterableImmutable<V>(this, _data, _usedData, -1, 2);
 }
 
 // Implementation is from "Hacker's Delight" by Henry S. Warren, Jr.,
@@ -628,6 +633,7 @@
 // and checks for concurrent modification.
 class _CompactIterable<E> extends Iterable<E> {
   final _HashBase _table;
+  // dart:core#_List (sdk/lib/_internal/vm/lib/array.dart).
   final List _data;
   final int _len;
   final int _offset;
@@ -646,6 +652,7 @@
 
 class _CompactIterator<E> implements Iterator<E> {
   final _HashBase _table;
+  // dart:core#_List (sdk/lib/_internal/vm/lib/array.dart).
   final List _data;
   final int _len;
   int _offset;
@@ -677,6 +684,58 @@
   E get current => _current as E;
 }
 
+// Iterates through _data[_offset + _step], _data[_offset + 2*_step], ...
+// and checks for concurrent modification.
+class _CompactIterableImmutable<E> extends Iterable<E> {
+  // _HashBase with _HashVMImmutableBase.
+  final _HashBase _table;
+  // dart:core#_ImmutableList (sdk/lib/_internal/vm/lib/array.dart).
+  final List _data;
+  final int _len;
+  final int _offset;
+  final int _step;
+
+  _CompactIterableImmutable(
+      this._table, this._data, this._len, this._offset, this._step);
+
+  Iterator<E> get iterator =>
+      new _CompactIteratorImmutable<E>(_table, _data, _len, _offset, _step);
+
+  int get length => _table.length;
+  bool get isEmpty => length == 0;
+  bool get isNotEmpty => !isEmpty;
+}
+
+class _CompactIteratorImmutable<E> implements Iterator<E> {
+  // _HashBase with _HashVMImmutableBase.
+  final _HashBase _table;
+  // dart:core#_ImmutableList (sdk/lib/_internal/vm/lib/array.dart).
+  final List _data;
+  final int _len;
+  int _offset;
+  final int _step;
+  final int _checkSum;
+  E? _current;
+
+  _CompactIteratorImmutable(
+      _HashBase table, this._data, this._len, this._offset, this._step)
+      : _table = table,
+        _checkSum = table._checkSum;
+
+  bool moveNext() {
+    _offset += _step;
+    if (_offset < _len) {
+      _current = internal.unsafeCast<E>(_data[_offset]);
+      return true;
+    } else {
+      _current = null;
+      return false;
+    }
+  }
+
+  E get current => _current as E;
+}
+
 abstract class _LinkedHashSetMixin<E> implements _HashBase {
   int _hashCode(e);
   bool _equals(e1, e2);
@@ -959,6 +1018,9 @@
 
   // Returns a mutable set.
   Set<E> toSet() => new _CompactLinkedHashSet<E>()..addAll(this);
+
+  Iterator<E> get iterator =>
+      new _CompactIteratorImmutable<E>(this, _data, _usedData, -1, 1);
 }
 
 class _CompactLinkedIdentityHashSet<E> extends _HashFieldBase
diff --git a/tools/VERSION b/tools/VERSION
index 18e7a2b..f4a203c 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 17
 PATCH 0
-PRERELEASE 82
+PRERELEASE 83
 PRERELEASE_PATCH 0
\ No newline at end of file