Version 2.17.0-42.0.dev

Merge commit '5dffffbf08811d19e748ed7d4216b37b56a4b80f' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart b/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart
index 514fcd9..4d2f6a1 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart
@@ -2,21 +2,32 @@
 // 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.
 
-/// Generates a Dart program for a given macro, which can be compiled and then
-/// passed as a precompiled kernel file to `MacroExecutor.loadMacro`.
+/// Generates a Dart program for a given set of macros, which can be compiled
+/// and then passed as a precompiled kernel file to `MacroExecutor.loadMacro`.
+///
+/// The [macroDeclarations] is a map from library URIs to macro classes for the
+/// macros supported. The macro classes are provided as a map from macro class
+/// names to the names of the macro class constructors.
 String bootstrapMacroIsolate(
-    String macroImport, String macroName, List<String> constructorNames) {
-  StringBuffer constructorEntries = new StringBuffer(
-      "MacroClassIdentifierImpl(Uri.parse('$macroImport'), '$macroName'): {");
-  for (String constructor in constructorNames) {
-    constructorEntries.writeln("'$constructor': "
-        "$macroName.${constructor.isEmpty ? 'new' : constructor},");
-  }
-  constructorEntries.writeln('},');
-  return template
-      .replaceFirst(_importMarker, 'import \'$macroImport\';')
-      .replaceFirst(
-          _macroConstructorEntriesMarker, constructorEntries.toString());
+    Map<String, Map<String, List<String>>> macroDeclarations) {
+  StringBuffer imports = new StringBuffer();
+  StringBuffer constructorEntries = new StringBuffer();
+  macroDeclarations
+      .forEach((String macroImport, Map<String, List<String>> macroClasses) {
+    imports.writeln('import \'$macroImport\';');
+    macroClasses.forEach((String macroName, List<String> constructorNames) {
+      constructorEntries
+          .writeln("MacroClassIdentifierImpl(Uri.parse('$macroImport'), "
+              "'$macroName'): {");
+      for (String constructor in constructorNames) {
+        constructorEntries.writeln("'$constructor': "
+            "$macroName.${constructor.isEmpty ? 'new' : constructor},");
+      }
+      constructorEntries.writeln('},');
+    });
+  });
+  return template.replaceFirst(_importMarker, imports.toString()).replaceFirst(
+      _macroConstructorEntriesMarker, constructorEntries.toString());
 }
 
 const String _importMarker = '{{IMPORT}}';
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/isolated_executor/isolated_executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/isolated_executor/isolated_executor.dart
index 849c662..57f0ec8 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/isolated_executor/isolated_executor.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/isolated_executor/isolated_executor.dart
@@ -182,7 +182,7 @@
               IsExactlyTypeRequest request =
                   new IsExactlyTypeRequest.deserialize(deserializer, zoneId);
               StaticType leftType = request.leftType.instance as StaticType;
-              StaticType rightType = request.leftType.instance as StaticType;
+              StaticType rightType = request.rightType.instance as StaticType;
               SerializableResponse response = new SerializableResponse(
                   response:
                       new BooleanValue(await leftType.isExactly(rightType)),
@@ -197,7 +197,7 @@
               IsSubtypeOfRequest request =
                   new IsSubtypeOfRequest.deserialize(deserializer, zoneId);
               StaticType leftType = request.leftType.instance as StaticType;
-              StaticType rightType = request.leftType.instance as StaticType;
+              StaticType rightType = request.rightType.instance as StaticType;
               SerializableResponse response = new SerializableResponse(
                   response:
                       new BooleanValue(await leftType.isSubtypeOf(rightType)),
diff --git a/pkg/_fe_analyzer_shared/test/macros/isolated_executor/isolated_executor_test.dart b/pkg/_fe_analyzer_shared/test/macros/isolated_executor/isolated_executor_test.dart
index a7f5491..7c242a4 100644
--- a/pkg/_fe_analyzer_shared/test/macros/isolated_executor/isolated_executor_test.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/isolated_executor/isolated_executor_test.dart
@@ -44,8 +44,11 @@
     var macroUri = simpleMacroFile.absolute.uri;
     var macroName = 'SimpleMacro';
 
-    var bootstrapContent =
-        bootstrapMacroIsolate(macroUri.toString(), macroName, ['', 'named']);
+    var bootstrapContent = bootstrapMacroIsolate({
+      macroUri.toString(): {
+        macroName: ['', 'named']
+      }
+    });
     var bootstrapFile = File(tmpDir.uri.resolve('main.dart').toFilePath())
       ..writeAsStringSync(bootstrapContent);
     var kernelOutputFile =
diff --git a/pkg/_fe_analyzer_shared/test/macros/isolated_executor/simple_macro.dart b/pkg/_fe_analyzer_shared/test/macros/isolated_executor/simple_macro.dart
index 035d96f..84ddb7a 100644
--- a/pkg/_fe_analyzer_shared/test/macros/isolated_executor/simple_macro.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/isolated_executor/simple_macro.dart
@@ -36,13 +36,13 @@
     }
     var classType =
         await builder.resolve(method.definingClass) as NamedStaticType;
-    if (!(await staticReturnType.isExactly(classType))) {
+    if (await staticReturnType.isExactly(classType)) {
       throw StateError(
           'The return type should not be exactly equal to the class type');
     }
-    if (!(await staticReturnType.isSubtypeOf(classType))) {
+    if (await staticReturnType.isSubtypeOf(classType)) {
       throw StateError(
-          'The return type should be a subtype of the class type!');
+          'The return type should not be a subtype of the class type!');
     }
 
     // Test the type declaration resolver
diff --git a/pkg/front_end/lib/src/fasta/builder_graph.dart b/pkg/front_end/lib/src/fasta/builder_graph.dart
index 9e2b434..fdae514 100644
--- a/pkg/front_end/lib/src/fasta/builder_graph.dart
+++ b/pkg/front_end/lib/src/fasta/builder_graph.dart
@@ -23,13 +23,15 @@
 class BuilderGraph implements Graph<Uri> {
   final Map<Uri, LibraryBuilder> builders;
 
+  final Map<Uri, List<Uri>> _neighborsCache = {};
+
   BuilderGraph(this.builders);
 
   @override
   Iterable<Uri> get vertices => builders.keys;
 
-  @override
-  Iterable<Uri> neighborsOf(Uri vertex) sync* {
+  List<Uri> _computeNeighborsOf(Uri vertex) {
+    List<Uri> neighbors = [];
     LibraryBuilder? library = builders[vertex];
     if (library == null) {
       throw "Library not found: $vertex";
@@ -40,20 +42,20 @@
         if (import.imported != null) {
           Uri uri = import.imported!.importUri;
           if (builders.containsKey(uri)) {
-            yield uri;
+            neighbors.add(uri);
           }
         }
       }
       for (Export export in library.exports) {
         Uri uri = export.exported.importUri;
         if (builders.containsKey(uri)) {
-          yield uri;
+          neighbors.add(uri);
         }
       }
       for (LibraryBuilder part in library.parts) {
         Uri uri = part.importUri;
         if (builders.containsKey(uri)) {
-          yield uri;
+          neighbors.add(uri);
         }
       }
     } else if (library is DillLibraryBuilder) {
@@ -61,7 +63,7 @@
       for (LibraryDependency dependency in library.library.dependencies) {
         Uri uri = dependency.targetLibrary.importUri;
         if (builders.containsKey(uri)) {
-          yield uri;
+          neighbors.add(uri);
         }
       }
 
@@ -69,9 +71,14 @@
       for (LibraryPart part in library.library.parts) {
         Uri uri = getPartUri(library.importUri, part);
         if (builders.containsKey(uri)) {
-          yield uri;
+          neighbors.add(uri);
         }
       }
     }
+    return neighbors;
   }
+
+  @override
+  Iterable<Uri> neighborsOf(Uri vertex) =>
+      _neighborsCache[vertex] ??= _computeNeighborsOf(vertex);
 }
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 76ab9eb8..2a1e8b7 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -361,7 +361,7 @@
             verify: c.options.verify);
         componentWithDill = buildResult.component;
       }
-      buildResult.macroApplications?.macroExecutor.close();
+      buildResult.macroApplications?.close();
       hierarchy ??= currentKernelTarget.loader.hierarchy;
       if (currentKernelTarget.classHierarchyChanges != null) {
         hierarchy.applyTreeChanges(
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 814b523..86144de 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -284,6 +284,7 @@
   }
 
   Version? _currentSdkVersion;
+
   Version get currentSdkVersion {
     if (_currentSdkVersion == null) {
       _parseCurrentSdkVersion();
@@ -464,7 +465,8 @@
       loader.finishNoSuchMethodForwarders();
       List<SourceClassBuilder> sourceClasses = loader.collectSourceClasses();
       if (macroApplications != null) {
-        await macroApplications.applyDefinitionMacros();
+        await macroApplications.applyDefinitionMacros(
+            loader.coreTypes, loader.hierarchy);
       }
       loader.finishNativeMethods();
       loader.finishPatchMethods();
diff --git a/pkg/front_end/lib/src/fasta/kernel/macro.dart b/pkg/front_end/lib/src/fasta/kernel/macro.dart
index 6d95bbf..3c8f11a 100644
--- a/pkg/front_end/lib/src/fasta/kernel/macro.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/macro.dart
@@ -5,9 +5,15 @@
 import 'package:_fe_analyzer_shared/src/macros/api.dart' hide TypeBuilder;
 import 'package:_fe_analyzer_shared/src/macros/executor.dart';
 import 'package:_fe_analyzer_shared/src/macros/executor_shared/introspection_impls.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/remote_instance.dart';
+import 'package:kernel/ast.dart' show DartType, DynamicType;
+import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/core_types.dart';
+import 'package:kernel/type_environment.dart';
 
 import '../builder/class_builder.dart';
 import '../builder/formal_parameter_builder.dart';
+import '../builder/library_builder.dart';
 import '../builder/member_builder.dart';
 import '../builder/named_type_builder.dart';
 import '../builder/type_builder.dart';
@@ -46,12 +52,39 @@
   }
 }
 
+class MacroApplication {
+  final ClassBuilder classBuilder;
+  final String constructorName;
+
+  // TODO(johnniwinther): Add support for arguments.
+
+  MacroApplication(this.classBuilder, this.constructorName);
+
+  late MacroInstanceIdentifier instanceIdentifier;
+}
+
+class MacroApplicationDataForTesting {
+  Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData = {};
+  Map<MemberBuilder, List<MacroExecutionResult>> memberDefinitionsResults = {};
+}
+
+class LibraryMacroApplicationData {
+  Map<SourceClassBuilder, ClassMacroApplicationData> classData = {};
+  Map<MemberBuilder, List<MacroApplication>> memberApplications = {};
+}
+
+class ClassMacroApplicationData {
+  List<MacroApplication>? classApplications;
+  Map<MemberBuilder, List<MacroApplication>> memberApplications = {};
+}
+
 class MacroApplications {
-  final MacroExecutor macroExecutor;
+  final MacroExecutor _macroExecutor;
   final Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData;
   final MacroApplicationDataForTesting? dataForTesting;
 
-  MacroApplications(this.macroExecutor, this.libraryData, this.dataForTesting) {
+  MacroApplications(
+      this._macroExecutor, this.libraryData, this.dataForTesting) {
     dataForTesting?.libraryData.addAll(libraryData);
   }
 
@@ -124,7 +157,7 @@
   Future<void> _applyTypeMacros(
       Declaration declaration, List<MacroApplication> macroApplications) async {
     for (MacroApplication macroApplication in macroApplications) {
-      await macroExecutor.executeTypesPhase(
+      await _macroExecutor.executeTypesPhase(
           macroApplication.instanceIdentifier, declaration);
     }
   }
@@ -151,7 +184,7 @@
       TypeResolver typeResolver,
       ClassIntrospector classIntrospector) async {
     for (MacroApplication macroApplication in macroApplications) {
-      await macroExecutor.executeDeclarationsPhase(
+      await _macroExecutor.executeDeclarationsPhase(
           macroApplication.instanceIdentifier,
           declaration,
           typeResolver,
@@ -160,7 +193,7 @@
   }
 
   Future<void> applyDeclarationMacros() async {
-    TypeResolver typeResolver = new _TypeResolver();
+    TypeResolver typeResolver = new _TypeResolver(this);
     ClassIntrospector classIntrospector = new _ClassIntrospector();
     for (MapEntry<SourceLibraryBuilder,
         LibraryMacroApplicationData> libraryEntry in libraryData.entries) {
@@ -186,19 +219,24 @@
       TypeDeclarationResolver typeDeclarationResolver) async {
     List<MacroExecutionResult> results = [];
     for (MacroApplication macroApplication in macroApplications) {
-      MacroExecutionResult result = await macroExecutor.executeDefinitionsPhase(
-          macroApplication.instanceIdentifier,
-          declaration,
-          typeResolver,
-          classIntrospector,
-          typeDeclarationResolver);
+      MacroExecutionResult result =
+          await _macroExecutor.executeDefinitionsPhase(
+              macroApplication.instanceIdentifier,
+              declaration,
+              typeResolver,
+              classIntrospector,
+              typeDeclarationResolver);
       results.add(result);
     }
     return results;
   }
 
-  Future<void> applyDefinitionMacros() async {
-    TypeResolver typeResolver = new _TypeResolver();
+  late TypeEnvironment typeEnvironment;
+
+  Future<void> applyDefinitionMacros(
+      CoreTypes coreTypes, ClassHierarchy classHierarchy) async {
+    typeEnvironment = new TypeEnvironment(coreTypes, classHierarchy);
+    TypeResolver typeResolver = new _TypeResolver(this);
     ClassIntrospector classIntrospector = new _ClassIntrospector();
     TypeDeclarationResolver typeDeclarationResolver =
         new _TypeDeclarationResolver();
@@ -222,126 +260,179 @@
       }
     }
   }
-}
 
-class MacroApplication {
-  final ClassBuilder classBuilder;
-  final String constructorName;
-  // TODO(johnniwinther): Add support for arguments.
-
-  MacroApplication(this.classBuilder, this.constructorName);
-
-  late MacroInstanceIdentifier instanceIdentifier;
-}
-
-class MacroApplicationDataForTesting {
-  Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData = {};
-  Map<MemberBuilder, List<MacroExecutionResult>> memberDefinitionsResults = {};
-}
-
-class LibraryMacroApplicationData {
-  Map<SourceClassBuilder, ClassMacroApplicationData> classData = {};
-  Map<MemberBuilder, List<MacroApplication>> memberApplications = {};
-}
-
-class ClassMacroApplicationData {
-  List<MacroApplication>? classApplications;
-  Map<MemberBuilder, List<MacroApplication>> memberApplications = {};
-}
-
-FunctionDeclaration createTopLevelFunctionDeclaration(
-    SourceProcedureBuilder builder) {
-  List<ParameterDeclarationImpl>? positionalParameters;
-  List<ParameterDeclarationImpl>? namedParameters;
-
-  List<FormalParameterBuilder>? formals = builder.formals;
-  if (formals == null) {
-    positionalParameters = namedParameters = const [];
-  } else {
-    positionalParameters = [];
-    namedParameters = [];
-    for (FormalParameterBuilder formal in formals) {
-      TypeAnnotationImpl type = computeTypeAnnotation(formal.type);
-      // TODO(johnniwinther): Support default values.
-      if (formal.isNamed) {
-        namedParameters.add(new ParameterDeclarationImpl(
-            id: _removeInstanceId++,
-            name: formal.name,
-            isRequired: formal.isNamedRequired,
-            isNamed: true,
-            type: type,
-            defaultValue: null));
-      } else {
-        positionalParameters.add(new ParameterDeclarationImpl(
-            id: _removeInstanceId++,
-            name: formal.name,
-            isRequired: formal.isRequired,
-            isNamed: false,
-            type: type,
-            defaultValue: null));
-      }
-    }
+  void close() {
+    _macroExecutor.close();
+    _staticTypeCache.clear();
+    _typeAnnotationCache.clear();
   }
 
-  return new FunctionDeclarationImpl(
-      id: _removeInstanceId++,
-      name: builder.name,
-      isAbstract: builder.isAbstract,
-      isExternal: builder.isExternal,
-      isGetter: builder.isGetter,
-      isSetter: builder.isSetter,
-      positionalParameters: positionalParameters,
-      namedParameters: namedParameters,
-      returnType: computeTypeAnnotation(builder.returnType),
-      // TODO(johnniwinther): Support typeParameters
-      typeParameters: const []);
+  FunctionDeclaration createTopLevelFunctionDeclaration(
+      SourceProcedureBuilder builder) {
+    List<ParameterDeclarationImpl>? positionalParameters;
+    List<ParameterDeclarationImpl>? namedParameters;
+
+    List<FormalParameterBuilder>? formals = builder.formals;
+    if (formals == null) {
+      positionalParameters = namedParameters = const [];
+    } else {
+      positionalParameters = [];
+      namedParameters = [];
+      for (FormalParameterBuilder formal in formals) {
+        TypeAnnotationImpl type =
+            computeTypeAnnotation(builder.library, formal.type);
+        // TODO(johnniwinther): Support default values.
+        if (formal.isNamed) {
+          namedParameters.add(new ParameterDeclarationImpl(
+              id: RemoteInstance.uniqueId,
+              name: formal.name,
+              isRequired: formal.isNamedRequired,
+              isNamed: true,
+              type: type,
+              defaultValue: null));
+        } else {
+          positionalParameters.add(new ParameterDeclarationImpl(
+              id: RemoteInstance.uniqueId,
+              name: formal.name,
+              isRequired: formal.isRequired,
+              isNamed: false,
+              type: type,
+              defaultValue: null));
+        }
+      }
+    }
+
+    return new FunctionDeclarationImpl(
+        id: RemoteInstance.uniqueId,
+        name: builder.name,
+        isAbstract: builder.isAbstract,
+        isExternal: builder.isExternal,
+        isGetter: builder.isGetter,
+        isSetter: builder.isSetter,
+        positionalParameters: positionalParameters,
+        namedParameters: namedParameters,
+        returnType: computeTypeAnnotation(builder.library, builder.returnType),
+        // TODO(johnniwinther): Support typeParameters
+        typeParameters: const []);
+  }
+
+  Map<TypeBuilder?, _NamedTypeAnnotationImpl> _typeAnnotationCache = {};
+
+  List<TypeAnnotationImpl> computeTypeAnnotations(
+      LibraryBuilder library, List<TypeBuilder>? typeBuilders) {
+    if (typeBuilders == null) return const [];
+    return new List.generate(typeBuilders.length,
+        (int index) => computeTypeAnnotation(library, typeBuilders[index]));
+  }
+
+  _NamedTypeAnnotationImpl _computeTypeAnnotation(
+      LibraryBuilder libraryBuilder, TypeBuilder? typeBuilder) {
+    if (typeBuilder != null) {
+      if (typeBuilder is NamedTypeBuilder) {
+        Object name = typeBuilder.name;
+        List<TypeAnnotationImpl> typeArguments =
+            computeTypeAnnotations(libraryBuilder, typeBuilder.arguments);
+        bool isNullable = typeBuilder.nullabilityBuilder.isNullable;
+        if (name is String) {
+          return new _NamedTypeAnnotationImpl(
+              typeBuilder: typeBuilder,
+              libraryBuilder: libraryBuilder,
+              id: RemoteInstance.uniqueId,
+              name: name,
+              typeArguments: typeArguments,
+              isNullable: isNullable);
+        } else if (name is QualifiedName) {
+          assert(name.qualifier is String);
+          return new _NamedTypeAnnotationImpl(
+              typeBuilder: typeBuilder,
+              libraryBuilder: libraryBuilder,
+              id: RemoteInstance.uniqueId,
+              name: '${name.qualifier}.${name.name}',
+              typeArguments: typeArguments,
+              isNullable: isNullable);
+        }
+      }
+    }
+    return new _NamedTypeAnnotationImpl(
+        typeBuilder: typeBuilder,
+        libraryBuilder: libraryBuilder,
+        id: RemoteInstance.uniqueId,
+        name: 'dynamic',
+        isNullable: false,
+        typeArguments: const []);
+  }
+
+  TypeAnnotationImpl computeTypeAnnotation(
+      LibraryBuilder libraryBuilder, TypeBuilder? typeBuilder) {
+    return _typeAnnotationCache[typeBuilder] ??=
+        _computeTypeAnnotation(libraryBuilder, typeBuilder);
+  }
+
+  StaticType resolveTypeAnnotation(_NamedTypeAnnotationImpl typeAnnotation) {
+    TypeBuilder? typeBuilder = typeAnnotation.typeBuilder;
+    LibraryBuilder libraryBuilder = typeAnnotation.libraryBuilder;
+    DartType dartType;
+    if (typeBuilder != null) {
+      dartType = typeBuilder.build(libraryBuilder);
+    } else {
+      dartType = const DynamicType();
+    }
+    return createStaticType(dartType);
+  }
+
+  Map<DartType, _StaticTypeImpl> _staticTypeCache = {};
+
+  StaticType createStaticType(DartType dartType) {
+    return _staticTypeCache[dartType] ??= new _StaticTypeImpl(this, dartType);
+  }
 }
 
-// TODO(johnniwinther): Cache remote instances when needed.
-int _removeInstanceId = 0;
+class _NamedTypeAnnotationImpl extends NamedTypeAnnotationImpl {
+  final TypeBuilder? typeBuilder;
+  final LibraryBuilder libraryBuilder;
 
-List<TypeAnnotationImpl> computeTypeAnnotations(
-    List<TypeBuilder>? typeBuilders) {
-  if (typeBuilders == null) return const [];
-  return new List.generate(typeBuilders.length,
-      (int index) => computeTypeAnnotation(typeBuilders[index]));
-}
-
-TypeAnnotationImpl computeTypeAnnotation(TypeBuilder? typeBuilder) {
-  if (typeBuilder != null) {
-    if (typeBuilder is NamedTypeBuilder) {
-      Object name = typeBuilder.name;
-      List<TypeAnnotationImpl> typeArguments =
-          computeTypeAnnotations(typeBuilder.arguments);
-      bool isNullable = typeBuilder.nullabilityBuilder.isNullable;
-      if (name is String) {
-        return new NamedTypeAnnotationImpl(
-            id: _removeInstanceId++,
+  _NamedTypeAnnotationImpl({
+    required this.typeBuilder,
+    required this.libraryBuilder,
+    required int id,
+    required bool isNullable,
+    required String name,
+    required List<TypeAnnotationImpl> typeArguments,
+  }) : super(
+            id: id,
+            isNullable: isNullable,
             name: name,
-            typeArguments: typeArguments,
-            isNullable: isNullable);
-      } else if (name is QualifiedName) {
-        assert(name.qualifier is String);
-        return new NamedTypeAnnotationImpl(
-            id: _removeInstanceId++,
-            name: '${name.qualifier}.${name.name}',
-            typeArguments: typeArguments,
-            isNullable: isNullable);
-      }
-    }
+            typeArguments: typeArguments);
+}
+
+class _StaticTypeImpl extends StaticType {
+  final MacroApplications macroApplications;
+  final DartType type;
+
+  _StaticTypeImpl(this.macroApplications, this.type);
+
+  @override
+  Future<bool> isExactly(covariant _StaticTypeImpl other) {
+    return new Future.value(type == other.type);
   }
-  return new NamedTypeAnnotationImpl(
-      id: _removeInstanceId++,
-      name: 'dynamic',
-      isNullable: false,
-      typeArguments: const []);
+
+  @override
+  Future<bool> isSubtypeOf(covariant _StaticTypeImpl other) {
+    return new Future.value(macroApplications.typeEnvironment
+        .isSubtypeOf(type, other.type, SubtypeCheckMode.withNullabilities));
+  }
 }
 
 class _TypeResolver implements TypeResolver {
+  final MacroApplications macroApplications;
+
+  _TypeResolver(this.macroApplications);
+
   @override
-  Future<StaticType> resolve(TypeAnnotation typeAnnotation) {
-    // TODO: implement resolve
-    throw new UnimplementedError('_TypeResolver.resolve');
+  Future<StaticType> resolve(
+      covariant _NamedTypeAnnotationImpl typeAnnotation) {
+    return new Future.value(
+        macroApplications.resolveTypeAnnotation(typeAnnotation));
   }
 }
 
diff --git a/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart b/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
index c880b78..dcaf732 100644
--- a/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
@@ -357,45 +357,42 @@
       if (formal.isSuperInitializingFormal) {
         superInitializingFormalIndex++;
         bool hasImmediatelyDeclaredInitializer = formal.hasDeclaredInitializer;
-        if (formal.type == null) {
-          DartType? type;
 
-          if (formal.isPositional) {
-            if (superInitializingFormalIndex < superFormals.length) {
-              FormalParameterBuilder correspondingSuperFormal =
-                  superFormals[superInitializingFormalIndex];
-              formal.hasDeclaredInitializer =
-                  hasImmediatelyDeclaredInitializer ||
-                      correspondingSuperFormal.hasDeclaredInitializer;
-              if (!hasImmediatelyDeclaredInitializer) {
-                (positionalSuperParameters ??= <int>[]).add(formalIndex);
-              }
-              type = correspondingSuperFormal.variable!.type;
-            } else {
-              // TODO(cstefantsova): Report an error.
+        FormalParameterBuilder? correspondingSuperFormal;
+
+        if (formal.isPositional) {
+          if (superInitializingFormalIndex < superFormals.length) {
+            correspondingSuperFormal =
+                superFormals[superInitializingFormalIndex];
+            formal.hasDeclaredInitializer = hasImmediatelyDeclaredInitializer ||
+                correspondingSuperFormal.hasDeclaredInitializer;
+            if (!hasImmediatelyDeclaredInitializer) {
+              (positionalSuperParameters ??= <int>[]).add(formalIndex);
             }
           } else {
-            FormalParameterBuilder? correspondingSuperFormal;
-            for (FormalParameterBuilder superFormal in superFormals) {
-              if (superFormal.isNamed && superFormal.name == formal.name) {
-                correspondingSuperFormal = superFormal;
-                break;
-              }
-            }
-
-            if (correspondingSuperFormal != null) {
-              formal.hasDeclaredInitializer =
-                  hasImmediatelyDeclaredInitializer ||
-                      correspondingSuperFormal.hasDeclaredInitializer;
-              if (!hasImmediatelyDeclaredInitializer) {
-                (namedSuperParameters ??= <String>[]).add(formal.name);
-              }
-              type = correspondingSuperFormal.variable!.type;
-            } else {
-              // TODO(cstefantsova): Report an error.
+            // TODO(cstefantsova): Report an error.
+          }
+        } else {
+          for (FormalParameterBuilder superFormal in superFormals) {
+            if (superFormal.isNamed && superFormal.name == formal.name) {
+              correspondingSuperFormal = superFormal;
+              break;
             }
           }
 
+          if (correspondingSuperFormal != null) {
+            formal.hasDeclaredInitializer = hasImmediatelyDeclaredInitializer ||
+                correspondingSuperFormal.hasDeclaredInitializer;
+            if (!hasImmediatelyDeclaredInitializer) {
+              (namedSuperParameters ??= <String>[]).add(formal.name);
+            }
+          } else {
+            // TODO(cstefantsova): Report an error.
+          }
+        }
+
+        if (formal.type == null) {
+          DartType? type = correspondingSuperFormal?.variable?.type;
           if (substitution.isNotEmpty && type != null) {
             type = substitute(type, substitution);
           }
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 e8b0af8..f481250 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -1364,26 +1364,42 @@
       dataForTesting!.macroDeclarationData.macrosAreAvailable = true;
     }
 
-    Set<ClassBuilder> macroClasses = {macroClassBuilder};
-    Set<Uri> macroLibraries = {macroLibraryBuilder.importUri};
+    Set<ClassBuilder> macroClasses = {};
 
-    for (SourceLibraryBuilder sourceLibraryBuilder in sourceLibraryBuilders) {
-      Iterator<Builder> iterator = sourceLibraryBuilder.iterator;
+    /// Libraries containing macros that need compilation.
+    Set<Uri> macroLibraries = {};
+
+    /// Libraries containing precompiled macro classes.
+    Set<Uri> precompiledMacroLibraries = {};
+
+    Map<MacroClass, Uri> precompiledMacroUris =
+        target.context.options.precompiledMacroUris;
+
+    for (LibraryBuilder libraryBuilder in libraryBuilders) {
+      Iterator<Builder> iterator = libraryBuilder.iterator;
       while (iterator.moveNext()) {
         Builder builder = iterator.current;
-        if (builder is SourceClassBuilder && builder.isMacro) {
-          macroClasses.add(builder);
-          macroLibraries.add(builder.library.importUri);
-          if (retainDataForTesting) {
-            (dataForTesting!.macroDeclarationData
-                    .macroDeclarations[builder.library.importUri] ??= [])
-                .add(builder.name);
+        if (builder is ClassBuilder && builder.isMacro) {
+          Uri libraryUri = builder.library.importUri;
+          MacroClass macroClass = new MacroClass(libraryUri, builder.name);
+          if (!precompiledMacroUris.containsKey(macroClass)) {
+            macroClasses.add(builder);
+            macroLibraries.add(libraryUri);
+            if (retainDataForTesting) {
+              (dataForTesting!.macroDeclarationData
+                      .macroDeclarations[libraryUri] ??= [])
+                  .add(builder.name);
+            }
+          } else {
+            precompiledMacroLibraries.add(libraryUri);
           }
         }
       }
     }
 
-    bool isDillLibrary(Uri uri) => _builders[uri]?.loader != this;
+    if (macroClasses.isEmpty) {
+      return;
+    }
 
     List<List<Uri>> computeCompilationSequence(Graph<Uri> libraryGraph,
         {required bool Function(Uri) filter}) {
@@ -1418,9 +1434,39 @@
       return layeredComponents;
     }
 
-    List<List<Uri>> compilationSteps = computeCompilationSequence(
-        new BuilderGraph(_builders),
-        filter: isDillLibrary);
+    Graph<Uri> graph = new BuilderGraph(_builders);
+
+    /// Libraries that are considered precompiled. These are libraries that are
+    /// either given as precompiled macro libraries, or libraries that these
+    /// depend upon.
+    // TODO(johnniwinther): Can we assume that the precompiled dills are
+    // self-contained?
+    Set<Uri> precompiledLibraries = {};
+
+    void addPrecompiledLibrary(Uri uri) {
+      if (precompiledLibraries.add(uri)) {
+        for (Uri neighbor in graph.neighborsOf(uri)) {
+          addPrecompiledLibrary(neighbor);
+        }
+      }
+    }
+
+    for (LibraryBuilder builder in _builders.values) {
+      if (builder.loader != this) {
+        addPrecompiledLibrary(builder.importUri);
+      } else if (precompiledMacroLibraries.contains(builder.importUri)) {
+        assert(
+            !macroLibraries.contains(builder.importUri),
+            "Macro library ${builder.importUri} is only partially "
+            "precompiled.");
+        addPrecompiledLibrary(builder.importUri);
+      }
+    }
+
+    bool isPrecompiledLibrary(Uri uri) => precompiledLibraries.contains(uri);
+
+    List<List<Uri>> compilationSteps =
+        computeCompilationSequence(graph, filter: isPrecompiledLibrary);
     if (retainDataForTesting) {
       dataForTesting!.macroDeclarationData.compilationSequence =
           compilationSteps;
diff --git a/pkg/front_end/lib/src/kernel_generator_impl.dart b/pkg/front_end/lib/src/kernel_generator_impl.dart
index 0deb368..2470a1a 100644
--- a/pkg/front_end/lib/src/kernel_generator_impl.dart
+++ b/pkg/front_end/lib/src/kernel_generator_impl.dart
@@ -172,7 +172,7 @@
     }
     // TODO(johnniwinther): Should we reuse the macro executor on subsequent
     // compilations where possible?
-    buildResult.macroApplications?.macroExecutor.close();
+    buildResult.macroApplications?.close();
 
     return new InternalCompilerResult(
         summary: summary,
diff --git a/pkg/front_end/test/explicit_creation_git_test.dart b/pkg/front_end/test/explicit_creation_git_test.dart
index 0f00042..3200635 100644
--- a/pkg/front_end/test/explicit_creation_git_test.dart
+++ b/pkg/front_end/test/explicit_creation_git_test.dart
@@ -104,7 +104,7 @@
     BuildResult buildResult = await kernelTarget.buildOutlines();
     buildResult = await kernelTarget.buildComponent(
         macroApplications: buildResult.macroApplications);
-    buildResult.macroApplications?.macroExecutor.close();
+    buildResult.macroApplications?.close();
   });
 
   print("Done in ${stopwatch.elapsedMilliseconds} ms. "
diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart
index d4e1b8c..02231dd 100644
--- a/pkg/front_end/test/fasta/testing/suite.dart
+++ b/pkg/front_end/test/fasta/testing/suite.dart
@@ -1856,7 +1856,7 @@
                   : context.verify);
           p = buildResult.component!;
         }
-        buildResult.macroApplications?.macroExecutor.close();
+        buildResult.macroApplications?.close();
 
         // To avoid possible crash in mixin transformation in the transformation
         // of the user of this linked dependency we have to transform this too.
@@ -1928,7 +1928,7 @@
           if (updateComments) {
             await instrumentation.fixSource(description.uri, false);
           } else {
-            buildResult.macroApplications?.macroExecutor.close();
+            buildResult.macroApplications?.close();
             return new Result<ComponentResult>(
                 new ComponentResult(description, p, userLibraries,
                     compilationSetup, sourceTarget),
@@ -1939,7 +1939,7 @@
           }
         }
       }
-      buildResult.macroApplications?.macroExecutor.close();
+      buildResult.macroApplications?.close();
       return pass(new ComponentResult(
           description, p, userLibraries, compilationSetup, sourceTarget));
     });
diff --git a/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro.dart b/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro.dart
index a5469f1..b686cc0 100644
--- a/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro.dart
+++ b/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro.dart
@@ -15,3 +15,21 @@
 }'''));
   }
 }
+
+macro class FunctionDefinitionMacro2 implements FunctionDefinitionMacro {
+  const FunctionDefinitionMacro2();
+
+  FutureOr<void> buildDefinitionForFunction(
+      FunctionDeclaration function, FunctionDefinitionBuilder builder) async {
+    if (function.positionalParameters.isEmpty) {
+      return;
+    }
+    StaticType returnType = await builder.resolve(function.returnType);
+    StaticType parameterType =
+        await builder.resolve(function.positionalParameters.first.type);
+    builder.augment(new FunctionBodyCode.fromString('''{
+  print('isExactly=${await returnType.isExactly(parameterType)}');
+  print('isSubtype=${await returnType.isSubtypeOf(parameterType)}');
+}'''));
+  }
+}
diff --git a/pkg/front_end/test/macro_application/data/tests/parameters.dart b/pkg/front_end/test/macro_application/data/tests/parameters.dart
index 41fcf36..bb606bb 100644
--- a/pkg/front_end/test/macro_application/data/tests/parameters.dart
+++ b/pkg/front_end/test/macro_application/data/tests/parameters.dart
@@ -4,30 +4,30 @@
 
 import 'package:macro/macro.dart';
 
-@FunctionDefinitionMacro1()
 /*member: topLevelFunction1:
 augment void topLevelFunction1(int a, ) {
   return 42;
 }*/
+@FunctionDefinitionMacro1()
 external void topLevelFunction1(int a);
 
-@FunctionDefinitionMacro1()
 /*member: topLevelFunction2:
 augment void topLevelFunction2(int a, int b, ) {
   return 42;
 }*/
+@FunctionDefinitionMacro1()
 external void topLevelFunction2(int a, int b);
 
-@FunctionDefinitionMacro1()
 /*member: topLevelFunction3:
 augment void topLevelFunction3(int a, [int? b, ]) {
   return 42;
 }*/
+@FunctionDefinitionMacro1()
 external void topLevelFunction3(int a, [int? b]);
 
-@FunctionDefinitionMacro1()
 /*member: topLevelFunction4:
 augment void topLevelFunction4(int a, {int? b, int? c, }) {
   return 42;
 }*/
+@FunctionDefinitionMacro1()
 external void topLevelFunction4(int a, {int? b, int? c});
diff --git a/pkg/front_end/test/macro_application/data/tests/subtypes.dart b/pkg/front_end/test/macro_application/data/tests/subtypes.dart
new file mode 100644
index 0000000..245908a
--- /dev/null
+++ b/pkg/front_end/test/macro_application/data/tests/subtypes.dart
@@ -0,0 +1,51 @@
+// 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:macro/macro.dart';
+
+class A {}
+
+class B1 {}
+
+class B2 extends B1 {}
+
+class C1 extends C2 {}
+
+class C2 {}
+
+class D1 {}
+
+class D2 {}
+
+/*member: topLevelFunction1:
+augment A topLevelFunction1(A a, ) {
+  print('isExactly=true');
+  print('isSubtype=true');
+}*/
+@FunctionDefinitionMacro2()
+external A topLevelFunction1(A a);
+
+/*member: topLevelFunction2:
+augment B2 topLevelFunction2(B1 a, ) {
+  print('isExactly=false');
+  print('isSubtype=true');
+}*/
+@FunctionDefinitionMacro2()
+external B2 topLevelFunction2(B1 a);
+
+/*member: topLevelFunction3:
+augment C2 topLevelFunction3(C1 a, ) {
+  print('isExactly=false');
+  print('isSubtype=false');
+}*/
+@FunctionDefinitionMacro2()
+external C2 topLevelFunction3(C1 a);
+
+/*member: topLevelFunction4:
+augment D2 topLevelFunction4(D1 a, ) {
+  print('isExactly=false');
+  print('isSubtype=false');
+}*/
+@FunctionDefinitionMacro2()
+external D2 topLevelFunction4(D1 a);
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 db171e8..d24b4ae 100644
--- a/pkg/front_end/test/macro_application/macro_application_test.dart
+++ b/pkg/front_end/test/macro_application/macro_application_test.dart
@@ -25,6 +25,13 @@
 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': [''],
+  }
+};
+
 Future<Uri> compileMacros(Directory directory) async {
   CompilerOptions options = new CompilerOptions();
   options.target = new VmTarget(new TargetFlags());
@@ -32,10 +39,9 @@
   options.environmentDefines = {};
   options.packagesFileUri = Platform.script.resolve('data/package_config.json');
 
-  CompilerResult? compilerResult = await compileScript({
-    'main.dart': bootstrapMacroIsolate(
-        'package:macro/macro.dart', 'FunctionDefinitionMacro1', [''])
-  }, options: options, requireMain: false);
+  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;
@@ -48,11 +54,14 @@
       await Directory.systemTemp.createTemp('macro_application');
 
   Uri macrosUri = await compileMacros(tempDirectory);
-  Map<MacroClass, Uri> precompiledMacroUris = {
-    new MacroClass(
-            Uri.parse('package:macro/macro.dart'), 'FunctionDefinitionMacro1'):
-        macrosUri
-  };
+  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'));
diff --git a/pkg/front_end/test/macros/data/package_config.json b/pkg/front_end/test/macros/data/package_config.json
index 9de8189..f176d49 100644
--- a/pkg/front_end/test/macros/data/package_config.json
+++ b/pkg/front_end/test/macros/data/package_config.json
@@ -6,6 +6,10 @@
       "rootUri": "pkgs/macro/lib/"
     },
     {
+      "name": "precompiled_macro",
+      "rootUri": "pkgs/precompiled_macro/lib/"
+    },
+    {
       "name": "_fe_analyzer_shared",
       "rootUri": "../../../../_fe_analyzer_shared/lib/"
     }
diff --git a/pkg/front_end/test/macros/data/pkgs/precompiled_macro/lib/precompiled_macro.dart b/pkg/front_end/test/macros/data/pkgs/precompiled_macro/lib/precompiled_macro.dart
new file mode 100644
index 0000000..8d112ca
--- /dev/null
+++ b/pkg/front_end/test/macros/data/pkgs/precompiled_macro/lib/precompiled_macro.dart
@@ -0,0 +1,11 @@
+// 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:_fe_analyzer_shared/src/macros/api.dart';
+
+import 'src/macro_base.dart';
+
+macro class PrecompiledMacro extends MacroBase implements Macro {
+  const PrecompiledMacro();
+}
diff --git a/pkg/front_end/test/macros/data/pkgs/precompiled_macro/lib/src/macro_base.dart b/pkg/front_end/test/macros/data/pkgs/precompiled_macro/lib/src/macro_base.dart
new file mode 100644
index 0000000..e503d1b
--- /dev/null
+++ b/pkg/front_end/test/macros/data/pkgs/precompiled_macro/lib/src/macro_base.dart
@@ -0,0 +1,7 @@
+// 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 MacroBase {
+  const MacroBase();
+}
diff --git a/pkg/front_end/test/macros/data/tests/all_precompiled.dart b/pkg/front_end/test/macros/data/tests/all_precompiled.dart
new file mode 100644
index 0000000..9310930
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/all_precompiled.dart
@@ -0,0 +1,16 @@
+// 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.
+
+/*library: 
+ macroClassIds=[package:precompiled_macro/precompiled_macro.dart/PrecompiledMacro],
+ macroInstanceIds=[package:precompiled_macro/precompiled_macro.dart/PrecompiledMacro/()],
+ macrosAreApplied,
+ macrosAreAvailable
+*/
+
+import 'package:precompiled_macro/precompiled_macro.dart';
+
+/*member: main:appliedMacros=[PrecompiledMacro.new]*/
+@PrecompiledMacro()
+void main() {}
diff --git a/pkg/front_end/test/macros/data/tests/applications.dart b/pkg/front_end/test/macros/data/tests/applications.dart
index 4201d8c..06bf716 100644
--- a/pkg/front_end/test/macros/data/tests/applications.dart
+++ b/pkg/front_end/test/macros/data/tests/applications.dart
@@ -4,8 +4,7 @@
 
 /*library: 
  compilationSequence=[
-  package:_fe_analyzer_shared/src/macros/api.dart,
-  package:macro/macro.dart,
+  package:_fe_analyzer_shared/src/macros/api.dart|package:macro/macro.dart,
   main.dart],
  macroClassIds=[
   package:macro/macro.dart/Macro1,
diff --git a/pkg/front_end/test/macros/data/tests/declare_macro.dart b/pkg/front_end/test/macros/data/tests/declare_macro.dart
index 056edbd..65611e1 100644
--- a/pkg/front_end/test/macros/data/tests/declare_macro.dart
+++ b/pkg/front_end/test/macros/data/tests/declare_macro.dart
@@ -3,9 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /*library: 
- compilationSequence=[
-  package:_fe_analyzer_shared/src/macros/api.dart,
-  main.dart],
+ compilationSequence=[main.dart|package:_fe_analyzer_shared/src/macros/api.dart],
  declaredMacros=[MyMacro],
  macrosAreAvailable
 */
diff --git a/pkg/front_end/test/macros/data/tests/declare_vs_apply/main.dart b/pkg/front_end/test/macros/data/tests/declare_vs_apply/main.dart
index 1a6c048..69ea910 100644
--- a/pkg/front_end/test/macros/data/tests/declare_vs_apply/main.dart
+++ b/pkg/front_end/test/macros/data/tests/declare_vs_apply/main.dart
@@ -4,8 +4,7 @@
 
 /*library: 
  compilationSequence=[
-  apply_lib_dep.dart|macro_lib_dep.dart|main_lib_dep.dart|package:_fe_analyzer_shared/src/macros/api.dart,
-  macro_lib.dart,
+  apply_lib_dep.dart|macro_lib.dart|macro_lib_dep.dart|main_lib_dep.dart|package:_fe_analyzer_shared/src/macros/api.dart,
   apply_lib.dart|main.dart],
  macroClassIds=[macro_lib.dart/Macro1],
  macroInstanceIds=[macro_lib.dart/Macro1/()],
diff --git a/pkg/front_end/test/macros/data/tests/direct_import.dart b/pkg/front_end/test/macros/data/tests/direct_import.dart
index a07f128..793a5f4 100644
--- a/pkg/front_end/test/macros/data/tests/direct_import.dart
+++ b/pkg/front_end/test/macros/data/tests/direct_import.dart
@@ -2,12 +2,7 @@
 // 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.
 
-/*library: 
- compilationSequence=[
-  package:_fe_analyzer_shared/src/macros/api.dart,
-  main.dart],
- macrosAreAvailable
-*/
+/*library: macrosAreAvailable*/
 
 // ignore: unused_import
 import 'package:_fe_analyzer_shared/src/macros/api.dart';
diff --git a/pkg/front_end/test/macros/data/tests/import_macro_builder.dart b/pkg/front_end/test/macros/data/tests/import_macro_builder.dart
index a07f128..793a5f4 100644
--- a/pkg/front_end/test/macros/data/tests/import_macro_builder.dart
+++ b/pkg/front_end/test/macros/data/tests/import_macro_builder.dart
@@ -2,12 +2,7 @@
 // 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.
 
-/*library: 
- compilationSequence=[
-  package:_fe_analyzer_shared/src/macros/api.dart,
-  main.dart],
- macrosAreAvailable
-*/
+/*library: macrosAreAvailable*/
 
 // ignore: unused_import
 import 'package:_fe_analyzer_shared/src/macros/api.dart';
diff --git a/pkg/front_end/test/macros/data/tests/import_macro_package.dart b/pkg/front_end/test/macros/data/tests/import_macro_package.dart
index 0c25eea..9619bb1 100644
--- a/pkg/front_end/test/macros/data/tests/import_macro_package.dart
+++ b/pkg/front_end/test/macros/data/tests/import_macro_package.dart
@@ -4,8 +4,7 @@
 
 /*library: 
  compilationSequence=[
-  package:_fe_analyzer_shared/src/macros/api.dart,
-  package:macro/macro.dart,
+  package:_fe_analyzer_shared/src/macros/api.dart|package:macro/macro.dart,
   main.dart],
  macrosAreAvailable
 */
diff --git a/pkg/front_end/test/macros/data/tests/import_macro_source/main.dart b/pkg/front_end/test/macros/data/tests/import_macro_source/main.dart
index dce865b..15c660c 100644
--- a/pkg/front_end/test/macros/data/tests/import_macro_source/main.dart
+++ b/pkg/front_end/test/macros/data/tests/import_macro_source/main.dart
@@ -4,8 +4,7 @@
 
 /*library: 
  compilationSequence=[
-  package:_fe_analyzer_shared/src/macros/api.dart,
-  macro_lib.dart,
+  macro_lib.dart|package:_fe_analyzer_shared/src/macros/api.dart,
   main.dart],
  macrosAreAvailable
 */
diff --git a/pkg/front_end/test/macros/data/tests/macro_declarations.dart b/pkg/front_end/test/macros/data/tests/macro_declarations.dart
index b6cb47f..c780d61 100644
--- a/pkg/front_end/test/macros/data/tests/macro_declarations.dart
+++ b/pkg/front_end/test/macros/data/tests/macro_declarations.dart
@@ -3,9 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /*library: 
- compilationSequence=[
-  package:_fe_analyzer_shared/src/macros/api.dart,
-  main.dart],
+ compilationSequence=[main.dart|package:_fe_analyzer_shared/src/macros/api.dart],
  declaredMacros=[
   Extends,
   ExtendsAlias,
diff --git a/pkg/front_end/test/macros/data/tests/multiple_macros/main.dart b/pkg/front_end/test/macros/data/tests/multiple_macros/main.dart
index 4aeb2a7..873d202 100644
--- a/pkg/front_end/test/macros/data/tests/multiple_macros/main.dart
+++ b/pkg/front_end/test/macros/data/tests/multiple_macros/main.dart
@@ -4,8 +4,7 @@
 
 /*library: 
  compilationSequence=[
-  package:_fe_analyzer_shared/src/macros/api.dart,
-  macro_lib1.dart|macro_lib2a.dart,
+  macro_lib1.dart|macro_lib2a.dart|package:_fe_analyzer_shared/src/macros/api.dart,
   macro_lib2b.dart,
   main.dart],
  macroClassIds=[
diff --git a/pkg/front_end/test/macros/data/tests/precompiled.dart b/pkg/front_end/test/macros/data/tests/precompiled.dart
new file mode 100644
index 0000000..5b29de2
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/precompiled.dart
@@ -0,0 +1,27 @@
+// 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.
+
+/*library: 
+ compilationSequence=[
+  package:macro/macro.dart,
+  main.dart],
+ macroClassIds=[
+  package:macro/macro.dart/Macro1,
+  package:precompiled_macro/precompiled_macro.dart/PrecompiledMacro],
+ macroInstanceIds=[
+  package:macro/macro.dart/Macro1/(),
+  package:precompiled_macro/precompiled_macro.dart/PrecompiledMacro/()],
+ macrosAreApplied,
+ macrosAreAvailable
+*/
+
+import 'package:precompiled_macro/precompiled_macro.dart';
+import 'package:macro/macro.dart';
+
+/*member: main:appliedMacros=[
+  Macro1.new,
+  PrecompiledMacro.new]*/
+@PrecompiledMacro()
+@Macro1()
+void main() {}
diff --git a/pkg/front_end/test/macros/data/tests/use_macro_package.dart b/pkg/front_end/test/macros/data/tests/use_macro_package.dart
index 691f58a..c3b123e 100644
--- a/pkg/front_end/test/macros/data/tests/use_macro_package.dart
+++ b/pkg/front_end/test/macros/data/tests/use_macro_package.dart
@@ -4,8 +4,7 @@
 
 /*library: 
  compilationSequence=[
-  package:_fe_analyzer_shared/src/macros/api.dart,
-  package:macro/macro.dart,
+  package:_fe_analyzer_shared/src/macros/api.dart|package:macro/macro.dart,
   main.dart],
  macroClassIds=[
   package:macro/macro.dart/Macro1,
diff --git a/pkg/front_end/test/macros/data/tests/use_macro_source/main.dart b/pkg/front_end/test/macros/data/tests/use_macro_source/main.dart
index 5bc5073..eff50a1 100644
--- a/pkg/front_end/test/macros/data/tests/use_macro_source/main.dart
+++ b/pkg/front_end/test/macros/data/tests/use_macro_source/main.dart
@@ -4,8 +4,7 @@
 
 /*library: 
  compilationSequence=[
-  package:_fe_analyzer_shared/src/macros/api.dart,
-  macro_lib.dart,
+  macro_lib.dart|package:_fe_analyzer_shared/src/macros/api.dart,
   main.dart],
  macroClassIds=[
   macro_lib.dart/Macro1,
diff --git a/pkg/front_end/test/macros/macro_test.dart b/pkg/front_end/test/macros/macro_test.dart
index 756e587..25ee5db 100644
--- a/pkg/front_end/test/macros/macro_test.dart
+++ b/pkg/front_end/test/macros/macro_test.dart
@@ -43,6 +43,11 @@
       CompilerOptions options, TestData testData) {
     TestMacroExecutor macroExecutor = new TestMacroExecutor();
     options.macroExecutorProvider = () async => macroExecutor;
+    Uri precompiledPackage =
+        Uri.parse('package:precompiled_macro/precompiled_macro.dart');
+    options.precompiledMacroUris = {
+      new MacroClass(precompiledPackage, 'PrecompiledMacro'): dummyUri,
+    };
     return macroExecutor;
   }
 }
@@ -295,10 +300,6 @@
   @override
   Future<MacroClassIdentifier> loadMacro(Uri library, String name,
       {Uri? precompiledKernelUri}) async {
-    if (precompiledKernelUri != null) {
-      throw new UnsupportedError(
-          'Precompiled kernel not supported for this implementation.');
-    }
     _MacroClassIdentifier id = new _MacroClassIdentifier(library, name);
     macroClasses.add(id);
     return id;
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart
new file mode 100644
index 0000000..f5b1bd9
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart
@@ -0,0 +1,16 @@
+// 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 S {
+  int s1;
+  int s2;
+  S([this.s1 = 1, this.s2 = 2]);
+}
+
+class C extends S {
+  int c1;
+  C(this.c1, [int super.s1, int x = 0, int super.s2]);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.strong.expect b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.strong.expect
new file mode 100644
index 0000000..3bd8f09
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.strong.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •([core::int s1 = #C1, core::int s2 = #C2]) → self::S
+    : self::S::s1 = s1, self::S::s2 = s2, super core::Object::•()
+    ;
+}
+class C extends self::S {
+  field core::int c1;
+  constructor •(core::int c1, [dynamic s1 = #C1, core::int x = #C3, dynamic s2 = #C2]) → self::C
+    : self::C::c1 = c1, super self::S::•(s1, s2)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 2
+  #C3 = 0
+}
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.strong.transformed.expect b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.strong.transformed.expect
new file mode 100644
index 0000000..3bd8f09
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.strong.transformed.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •([core::int s1 = #C1, core::int s2 = #C2]) → self::S
+    : self::S::s1 = s1, self::S::s2 = s2, super core::Object::•()
+    ;
+}
+class C extends self::S {
+  field core::int c1;
+  constructor •(core::int c1, [dynamic s1 = #C1, core::int x = #C3, dynamic s2 = #C2]) → self::C
+    : self::C::c1 = c1, super self::S::•(s1, s2)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 2
+  #C3 = 0
+}
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.textual_outline.expect b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.textual_outline.expect
new file mode 100644
index 0000000..7acd1b7
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.textual_outline.expect
@@ -0,0 +1,10 @@
+class S {
+  int s1;
+  int s2;
+  S([this.s1 = 1, this.s2 = 2]);
+}
+class C extends S {
+  int c1;
+  C(this.c1, [int super.s1, int x = 0, int super.s2]);
+}
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.expect b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.expect
new file mode 100644
index 0000000..3bd8f09
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •([core::int s1 = #C1, core::int s2 = #C2]) → self::S
+    : self::S::s1 = s1, self::S::s2 = s2, super core::Object::•()
+    ;
+}
+class C extends self::S {
+  field core::int c1;
+  constructor •(core::int c1, [dynamic s1 = #C1, core::int x = #C3, dynamic s2 = #C2]) → self::C
+    : self::C::c1 = c1, super self::S::•(s1, s2)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 2
+  #C3 = 0
+}
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.modular.expect b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.modular.expect
new file mode 100644
index 0000000..3bd8f09
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.modular.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •([core::int s1 = #C1, core::int s2 = #C2]) → self::S
+    : self::S::s1 = s1, self::S::s2 = s2, super core::Object::•()
+    ;
+}
+class C extends self::S {
+  field core::int c1;
+  constructor •(core::int c1, [dynamic s1 = #C1, core::int x = #C3, dynamic s2 = #C2]) → self::C
+    : self::C::c1 = c1, super self::S::•(s1, s2)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 2
+  #C3 = 0
+}
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.outline.expect b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.outline.expect
new file mode 100644
index 0000000..aae570e
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.outline.expect
@@ -0,0 +1,18 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •([core::int s1 = 1, core::int s2 = 2]) → self::S
+    ;
+}
+class C extends self::S {
+  field core::int c1;
+  constructor •(core::int c1, [dynamic s1 = 1, core::int x = 0, dynamic s2 = 2]) → self::C
+    : self::C::c1 = c1
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.transformed.expect b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.transformed.expect
new file mode 100644
index 0000000..3bd8f09
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.transformed.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •([core::int s1 = #C1, core::int s2 = #C2]) → self::S
+    : self::S::s1 = s1, self::S::s2 = s2, super core::Object::•()
+    ;
+}
+class C extends self::S {
+  field core::int c1;
+  constructor •(core::int c1, [dynamic s1 = #C1, core::int x = #C3, dynamic s2 = #C2]) → self::C
+    : self::C::c1 = c1, super self::S::•(s1, s2)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 2
+  #C3 = 0
+}
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index 86a420c..751ebe1 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -100,10 +100,10 @@
 general/issue43363: FormatterCrash
 general/issue45490: FormatterCrash
 general/issue45700.crash: FormatterCrash
-general/issue_46886: FormatterCrash
 general/issue47495: FormatterCrash
 general/issue47728_2: FormatterCrash
 general/issue47728_3: FormatterCrash
+general/issue_46886: FormatterCrash
 general/macro_class: FormatterCrash
 general/many_errors: FormatterCrash
 general/missing_prefix_name: FormatterCrash
@@ -219,6 +219,7 @@
 super_parameters/simple_inference: FormatterCrash
 super_parameters/simple_named_super_parameters: FormatterCrash
 super_parameters/simple_positional_super_parameters: FormatterCrash
+super_parameters/super_parameters_with_types_and_default_values: FormatterCrash
 super_parameters/synthesized_super_constructor_with_parameters: FormatterCrash
 super_parameters/type_alias_in_supertype: FormatterCrash
 super_parameters/typed_super_parameter: FormatterCrash
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index f99d05f..24fad8f 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.dart
@@ -309,7 +309,7 @@
         output: output,
         omitPlatform: omitPlatform,
         supportAdditionalDills: supportAdditionalDills);
-    buildResult.macroApplications?.macroExecutor.close();
+    buildResult.macroApplications?.close();
     return kernelTarget;
   }
 
@@ -384,7 +384,7 @@
     buildResult = await kernelTarget.buildComponent(
         macroApplications: buildResult.macroApplications,
         verify: c.options.verify);
-    buildResult.macroApplications?.macroExecutor.close();
+    buildResult.macroApplications?.close();
     Component component = buildResult.component!;
     if (c.options.debugDump) {
       printComponentText(component,
diff --git a/sdk/lib/core/string.dart b/sdk/lib/core/string.dart
index 8764498..d3ec0f0 100644
--- a/sdk/lib/core/string.dart
+++ b/sdk/lib/core/string.dart
@@ -81,7 +81,7 @@
 /// ```
 /// For a character outside the Basic Multilingual Plane (plane 0) that is
 /// composed of a surrogate pair, [runes] combines the pair and returns a
-/// single integer.  For example, the Unicode character for a
+/// single integer. For example, the Unicode character for a
 /// musical G-clef ('𝄞') with rune value 0x1D11E consists of a UTF-16 surrogate
 /// pair: `0xD834` and `0xDD1E`. Using [codeUnits] returns the surrogate pair,
 /// and using `runes` returns their combined value:
@@ -198,7 +198,7 @@
   /// The length of the string.
   ///
   /// Returns the number of UTF-16 code units in this string. The number
-  /// of [runes] might be fewer, if the string contains characters outside
+  /// of [runes] might be fewer if the string contains characters outside
   /// the Basic Multilingual Plane (plane 0):
   /// ```dart
   /// 'Dart'.length;          // 4
@@ -346,7 +346,7 @@
   /// result = string.substring(1, 4); // 'art'
   /// ```
   ///
-  /// Both [start] and [end] must be non-negative and no greater than [length], and
+  /// Both [start] and [end] must be non-negative and no greater than [length];
   /// [end], if provided, must be greater than or equal to [start].
   String substring(int start, [int? end]);
 
@@ -494,7 +494,7 @@
   /// Example:
   /// ```dart
   /// '0.0001'.replaceFirst(RegExp(r'0'), ''); // '.0001'
-  /// '0.0001'.replaceFirst(RegExp(r'0'), '7', 1);  // '0.7001'
+  /// '0.0001'.replaceFirst(RegExp(r'0'), '7', 1); // '0.7001'
   /// ```
   String replaceFirst(Pattern from, String to, [int startIndex = 0]);
 
@@ -724,6 +724,44 @@
 }
 
 /// The runes (integer Unicode code points) of a [String].
+///
+/// The characters of a string are encoded in UTF-16. Decoding UTF-16, which
+/// combines surrogate pairs, yields Unicode code points. Following a similar
+/// terminology to Go, Dart uses the name 'rune' for an integer representing a
+/// Unicode code point. Use the `runes` property to get the runes of a string.
+///
+/// Example:
+/// ```dart
+/// const string = 'Dart';
+/// final runes = string.runes.toList();
+/// print(runes); // [68, 97, 114, 116]
+/// ```
+///
+/// For a character outside the Basic Multilingual Plane (plane 0) that is
+/// composed of a surrogate pair, runes combines the pair and returns a
+/// single integer.
+///
+/// For example, the Unicode character for "Man" emoji ('👨', `U+1F468`) is
+/// combined from the surrogates `U+d83d` and `U+dc68`.
+///
+/// Example:
+/// ```dart
+/// const emojiMan = '👨';
+/// print(emojiMan.runes); // (128104)
+///
+/// // Surrogate pairs:
+/// for (final item in emojiMan.codeUnits) {
+///   print(item.toRadixString(16));
+///   // d83d
+///   // dc68
+/// }
+/// ```
+///
+/// **See also:**
+/// * [Runes and grapheme clusters](
+/// https://dart.dev/guides/language/language-tour#runes-and-grapheme-clusters)
+/// in
+/// [A tour of the Dart language](https://dart.dev/guides/language/language-tour).
 class Runes extends Iterable<int> {
   /// The string that this is the runes of.
   final String string;
diff --git a/tools/VERSION b/tools/VERSION
index 3f0e9b0..58a37e5 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 17
 PATCH 0
-PRERELEASE 41
+PRERELEASE 42
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/bots/dart_sdk.py b/tools/bots/dart_sdk.py
index d14f3ce..934906f 100755
--- a/tools/bots/dart_sdk.py
+++ b/tools/bots/dart_sdk.py
@@ -79,7 +79,7 @@
 def CreateUploadAPIDocs():
     dartdoc_dir = BuildRootPath('gen-dartdocs')
     dartdoc_zip = BuildRootPath('dartdocs-api.zip')
-    if CHANNEL == bot_utils.Channel.TRY:
+    if CHANNEL == bot_utils.Channel.TRY or DART_EXPERIMENTAL_BUILD == '1':
         BuildDartdocAPIDocs(dartdoc_dir)
     else:
         UploadApiLatestFile()
@@ -222,12 +222,13 @@
 
     BUILD_OS = utils.GuessOS()
     BUILDER_NAME = os.environ.get('BUILDBOT_BUILDERNAME')
+    DART_EXPERIMENTAL_BUILD = os.environ.get('DART_EXPERIMENTAL_BUILD')
     CHANNEL = bot_utils.GetChannelFromName(BUILDER_NAME)
 
     if command == 'api_docs':
         if BUILD_OS == 'linux':
             CreateUploadAPIDocs()
-    elif CHANNEL != bot_utils.Channel.TRY:
+    elif CHANNEL != bot_utils.Channel.TRY and DART_EXPERIMENTAL_BUILD != '1':
         for arch in archs:
             print('Create and upload sdk zip for ' + arch)
             sdk_path = BuildRootPath('dart-sdk', arch=arch)