Version 2.17.0-71.0.dev

Merge commit '0d4595d5dc39c882232f2a917f91b25203972181' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
index a4c2df3..f01ccb8 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
@@ -85,8 +85,11 @@
 
   /// Combines multiple [MacroExecutionResult]s into a single library
   /// augmentation file, and returns a [String] representing that file.
-  Future<String> buildAugmentationLibrary(
-      Iterable<MacroExecutionResult> macroResults);
+  ///
+  /// The [resolveIdentifier] argument should return the import uri to be used
+  /// for that identifier.
+  String buildAugmentationLibrary(Iterable<MacroExecutionResult> macroResults,
+      Uri Function(Identifier) resolveIdentifier);
 
   /// Tell the executor to shut down and clean up any resources it may have
   /// allocated.
@@ -243,10 +246,6 @@
 /// All modifications are expressed in terms of library augmentation
 /// declarations.
 abstract class MacroExecutionResult implements Serializable {
-  /// Any library imports that should be added to support the code used in
-  /// the augmentations.
-  Iterable<DeclarationCode> get imports;
-
   /// Any augmentations that should be applied as a result of executing a macro.
   Iterable<DeclarationCode> get augmentations;
 }
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/augmentation_library.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/augmentation_library.dart
new file mode 100644
index 0000000..cd0e198
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/augmentation_library.dart
@@ -0,0 +1,49 @@
+// 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 '../api.dart';
+import '../executor.dart';
+
+/// A mixin which provides a shared implementation of
+/// [MacroExecutor.buildAugmentationLibrary].
+mixin AugmentationLibraryBuilder on MacroExecutor {
+  @override
+  String buildAugmentationLibrary(Iterable<MacroExecutionResult> macroResults,
+      Uri Function(Identifier) resolveIdentifier) {
+    StringBuffer importsBuffer = new StringBuffer();
+    StringBuffer directivesBuffer = new StringBuffer();
+    Map<Uri, String> importPrefixes = {};
+    int nextPrefix = 0;
+
+    void buildCode(Code code) {
+      for (Object part in code.parts) {
+        if (part is String) {
+          directivesBuffer.write(part);
+        } else if (part is Code) {
+          buildCode(part);
+        } else if (part is Identifier) {
+          Uri uri = resolveIdentifier(part);
+          String prefix = importPrefixes.putIfAbsent(uri, () {
+            String prefix = 'i${nextPrefix++}';
+            importsBuffer.writeln("import '$uri' as $prefix;");
+            return prefix;
+          });
+          directivesBuffer.write('$prefix.${part.name}');
+        } else {
+          throw new ArgumentError(
+              'Code objects only support String, Identifier, and Code '
+              'instances but got $part which was not one of those.');
+        }
+      }
+    }
+
+    for (MacroExecutionResult result in macroResults) {
+      for (DeclarationCode augmentation in result.augmentations) {
+        buildCode(augmentation);
+        directivesBuffer.writeln();
+      }
+    }
+    return '$importsBuffer\n\n$directivesBuffer';
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/builder_impls.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/builder_impls.dart
index 099c58e..b591a3e 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/builder_impls.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/builder_impls.dart
@@ -16,11 +16,8 @@
 
   /// Creates and returns a [MacroExecutionResult] out of the [_augmentations]
   /// created by this builder.
-  MacroExecutionResult get result => new MacroExecutionResultImpl(
-        augmentations: _augmentations,
-        // TODO: Implement `imports`, or possibly drop it?
-        imports: [],
-      );
+  MacroExecutionResult get result =>
+      new MacroExecutionResultImpl(augmentations: _augmentations);
 
   TypeBuilderBase({List<DeclarationCode>? parentAugmentations})
       : _augmentations = parentAugmentations ?? [];
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/response_impls.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/response_impls.dart
index 08a94ed..39d1f61 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/response_impls.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/response_impls.dart
@@ -209,12 +209,8 @@
   @override
   final List<DeclarationCode> augmentations;
 
-  @override
-  final List<DeclarationCode> imports;
-
   MacroExecutionResultImpl({
     required this.augmentations,
-    required this.imports,
   });
 
   factory MacroExecutionResultImpl.deserialize(Deserializer deserializer) {
@@ -226,19 +222,7 @@
           hasNext = deserializer.moveNext())
         deserializer.expectCode()
     ];
-    deserializer.moveNext();
-    deserializer.expectList();
-    List<DeclarationCode> imports = [
-      for (bool hasNext = deserializer.moveNext();
-          hasNext;
-          hasNext = deserializer.moveNext())
-        deserializer.expectCode()
-    ];
-
-    return new MacroExecutionResultImpl(
-      augmentations: augmentations,
-      imports: imports,
-    );
+    return new MacroExecutionResultImpl(augmentations: augmentations);
   }
 
   void serialize(Serializer serializer) {
@@ -247,10 +231,5 @@
       augmentation.serialize(serializer);
     }
     serializer.endList();
-    serializer.startList();
-    for (DeclarationCode import in imports) {
-      import.serialize(serializer);
-    }
-    serializer.endList();
   }
 }
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart
index 2b93d2c..e45d120 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart
@@ -7,6 +7,7 @@
 import 'dart:mirrors';
 
 import 'isolate_mirrors_impl.dart';
+import '../executor_shared/augmentation_library.dart';
 import '../executor_shared/introspection_impls.dart';
 import '../executor_shared/protocol.dart';
 import '../executor_shared/remote_instance.dart';
@@ -23,7 +24,8 @@
 ///
 /// All actual work happens in a separate [Isolate], and this class serves as
 /// a bridge between that isolate and the language frontends.
-class _IsolateMirrorMacroExecutor implements MacroExecutor {
+class _IsolateMirrorMacroExecutor extends MacroExecutor
+    with AugmentationLibraryBuilder {
   /// The actual isolate doing macro loading and execution.
   final Isolate _macroIsolate;
 
@@ -78,13 +80,6 @@
   }
 
   @override
-  Future<String> buildAugmentationLibrary(
-      Iterable<MacroExecutionResult> macroResults) {
-    // TODO: implement buildAugmentationLibrary
-    throw new UnimplementedError();
-  }
-
-  @override
   void close() {
     _onClose();
     _macroIsolate.kill();
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 eeeeb45..198d388 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
@@ -8,6 +8,7 @@
 import 'package:_fe_analyzer_shared/src/macros/executor_shared/remote_instance.dart';
 
 import '../api.dart';
+import '../executor_shared/augmentation_library.dart';
 import '../executor_shared/introspection_impls.dart';
 import '../executor_shared/protocol.dart';
 import '../executor_shared/response_impls.dart';
@@ -28,19 +29,13 @@
 ///
 /// Spawned isolates are not ran in the same isolate group, so objects are
 /// serialized between isolates.
-class _IsolatedMacroExecutor implements MacroExecutor {
+class _IsolatedMacroExecutor extends MacroExecutor
+    with AugmentationLibraryBuilder {
   /// Individual executors indexed by [MacroClassIdentifier] or
   /// [MacroInstanceIdentifier].
   final _executors = <Object, _SingleIsolatedMacroExecutor>{};
 
   @override
-  Future<String> buildAugmentationLibrary(
-      Iterable<MacroExecutionResult> macroResults) {
-    // TODO: implement buildAugmentationLibrary
-    throw new UnimplementedError();
-  }
-
-  @override
   void close() {
     for (_SingleIsolatedMacroExecutor executor in _executors.values) {
       executor.close();
@@ -370,8 +365,8 @@
 
   /// These calls are handled by the higher level executor.
   @override
-  Future<String> buildAugmentationLibrary(
-          Iterable<MacroExecutionResult> macroResults) =>
+  String buildAugmentationLibrary(Iterable<MacroExecutionResult> macroResults,
+          Uri Function(Identifier) resolveIdentifier) =>
       throw new StateError('Unreachable');
 
   @override
diff --git a/pkg/_fe_analyzer_shared/test/macros/executor_shared/augmentation_library_test.dart b/pkg/_fe_analyzer_shared/test/macros/executor_shared/augmentation_library_test.dart
new file mode 100644
index 0000000..78d6908
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/macros/executor_shared/augmentation_library_test.dart
@@ -0,0 +1,109 @@
+// 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/executor_shared/remote_instance.dart';
+import 'package:test/fake.dart';
+import 'package:test/test.dart';
+
+import 'package:_fe_analyzer_shared/src/macros/executor.dart';
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/augmentation_library.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/response_impls.dart';
+
+import '../util.dart';
+
+void main() {
+  group('AugmentationLibraryBuilder', () {
+    test('can combine multiple execution results', () {
+      var results = [
+        for (var i = 0; i < 2; i++)
+          MacroExecutionResultImpl(augmentations: [
+            for (var j = 0; j < 3; j++)
+              DeclarationCode.fromParts([
+                'augment class Foo$i$j {\n',
+                DeclarationCode.fromParts([
+                  'int get i => $i;\n',
+                  'int get j => $j;\n',
+                ]),
+                '}',
+              ]),
+          ]),
+      ];
+      var library = _TestExecutor().buildAugmentationLibrary(
+          results, (Identifier i) => (i as TestIdentifier).libraryImportUri);
+      expect(library, equalsIgnoringWhitespace('''
+        augment class Foo00 {
+          int get i => 0;
+          int get j => 0;
+        }
+        augment class Foo01 {
+          int get i => 0;
+          int get j => 1;
+        }
+        augment class Foo02 {
+          int get i => 0;
+          int get j => 2;
+        }
+        augment class Foo10 {
+          int get i => 1;
+          int get j => 0;
+        }
+        augment class Foo11 {
+          int get i => 1;
+          int get j => 1;
+        }
+        augment class Foo12 {
+          int get i => 1;
+          int get j => 2;
+        }
+      '''));
+    });
+
+    test('can add imports for identifiers', () {
+      var fooIdentifier = TestIdentifier(
+          id: RemoteInstance.uniqueId,
+          name: 'Foo',
+          libraryImportUri: Uri.parse('package:foo/foo.dart'));
+      var barIdentifier = TestIdentifier(
+          id: RemoteInstance.uniqueId,
+          name: 'Bar',
+          libraryImportUri: Uri.parse('package:bar/bar.dart'));
+      var builderIdentifier = TestIdentifier(
+          id: RemoteInstance.uniqueId,
+          name: 'Builder',
+          libraryImportUri: Uri.parse('package:builder/builder.dart'));
+      var results = [
+        MacroExecutionResultImpl(augmentations: [
+          DeclarationCode.fromParts([
+            'class FooBuilder<T extends ',
+            fooIdentifier,
+            '> implements ',
+            builderIdentifier,
+            '<',
+            barIdentifier,
+            '<T>> {\n',
+            barIdentifier,
+            '<T> build() => new ',
+            barIdentifier,
+            '();\n}',
+          ]),
+        ])
+      ];
+      var library = _TestExecutor().buildAugmentationLibrary(
+          results, (Identifier i) => (i as TestIdentifier).libraryImportUri);
+      expect(library, equalsIgnoringWhitespace('''
+        import 'package:foo/foo.dart' as i0;
+        import 'package:builder/builder.dart' as i1;
+        import 'package:bar/bar.dart' as i2;
+
+        class FooBuilder<T extends i0.Foo> implements i1.Builder<i2.Bar<T>> {
+          i2.Bar<T> build() => new i2.Bar();
+        }
+      '''));
+    });
+  });
+}
+
+class _TestExecutor extends MacroExecutor
+    with AugmentationLibraryBuilder, Fake {}
diff --git a/pkg/_fe_analyzer_shared/test/macros/util.dart b/pkg/_fe_analyzer_shared/test/macros/util.dart
index 831a4f8..4af5f1a 100644
--- a/pkg/_fe_analyzer_shared/test/macros/util.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/util.dart
@@ -93,7 +93,7 @@
   }
 }
 
-// Doesn't handle generics etc but thats ok for now
+/// Doesn't handle generics etc but thats ok for now
 class TestNamedStaticType implements NamedStaticType {
   final IdentifierImpl identifier;
   final String library;
@@ -114,6 +114,15 @@
       (library == other.library && identifier.name == other.identifier.name);
 }
 
+/// An identifier that knows what URI should be used to import it.
+class TestIdentifier extends IdentifierImpl {
+  final Uri libraryImportUri;
+
+  TestIdentifier(
+      {required int id, required String name, required this.libraryImportUri})
+      : super(id: id, name: name);
+}
+
 extension DebugCodeString on Code {
   StringBuffer debugString([StringBuffer? buffer]) {
     buffer ??= StringBuffer();
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 9bad9b3..818e97f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -423,7 +423,7 @@
       loader.buildClassHierarchy(sourceClassBuilders, objectClassBuilder);
       loader.checkSupertypes(sourceClassBuilders, enumClass);
       if (macroApplications != null) {
-        await macroApplications.applyDeclarationMacros();
+        await macroApplications.applyDeclarationMacros(loader.hierarchyBuilder);
       }
       loader.buildClassHierarchyMembers(sourceClassBuilders);
       loader.computeHierarchy();
@@ -474,8 +474,7 @@
       loader.finishNoSuchMethodForwarders();
       List<SourceClassBuilder>? sourceClasses = loader.collectSourceClasses();
       if (macroApplications != null) {
-        await macroApplications.applyDefinitionMacros(
-            loader.coreTypes, loader.hierarchy);
+        await macroApplications.applyDefinitionMacros();
       }
       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 a637145..8b331c0 100644
--- a/pkg/front_end/lib/src/fasta/kernel/macro.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/macro.dart
@@ -2,16 +2,16 @@
 // 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.
 
-// TODO: Only import `Identifier` under a prefix if/when the presubmit check
-// allows duplicate imports if they have different prefixes.
 import 'package:_fe_analyzer_shared/src/macros/api.dart' as macro;
-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:_fe_analyzer_shared/src/macros/executor.dart' as macro;
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/introspection_impls.dart'
+    as macro;
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/remote_instance.dart'
+    as macro;
 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 'package:kernel/src/types.dart';
+import 'package:kernel/type_environment.dart' show SubtypeCheckMode;
 
 import '../builder/class_builder.dart';
 import '../builder/formal_parameter_builder.dart';
@@ -29,8 +29,8 @@
 final Uri macroLibraryUri =
     Uri.parse('package:_fe_analyzer_shared/src/macros/api.dart');
 const String macroClassName = 'Macro';
-final IdentifierImpl dynamicIdentifier =
-    new IdentifierImpl(id: RemoteInstance.uniqueId, name: 'dynamic');
+final macro.IdentifierImpl dynamicIdentifier = new macro.IdentifierImpl(
+    id: macro.RemoteInstance.uniqueId, name: 'dynamic');
 
 class MacroDeclarationData {
   bool macrosAreAvailable = false;
@@ -65,14 +65,16 @@
 
   MacroApplication(this.classBuilder, this.constructorName);
 
-  late MacroInstanceIdentifier instanceIdentifier;
+  late macro.MacroInstanceIdentifier instanceIdentifier;
 }
 
 class MacroApplicationDataForTesting {
   Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData = {};
-  Map<MemberBuilder, List<MacroExecutionResult>> memberTypesResults = {};
-  Map<MemberBuilder, List<MacroExecutionResult>> memberDeclarationsResults = {};
-  Map<MemberBuilder, List<MacroExecutionResult>> memberDefinitionsResults = {};
+  Map<MemberBuilder, List<macro.MacroExecutionResult>> memberTypesResults = {};
+  Map<MemberBuilder, List<macro.MacroExecutionResult>>
+      memberDeclarationsResults = {};
+  Map<MemberBuilder, List<macro.MacroExecutionResult>>
+      memberDefinitionsResults = {};
 }
 
 class LibraryMacroApplicationData {
@@ -86,7 +88,7 @@
 }
 
 class MacroApplications {
-  final MacroExecutor _macroExecutor;
+  final macro.MacroExecutor _macroExecutor;
   final Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData;
   final MacroApplicationDataForTesting? dataForTesting;
 
@@ -96,13 +98,13 @@
   }
 
   static Future<MacroApplications> loadMacroIds(
-      MacroExecutor macroExecutor,
+      macro.MacroExecutor macroExecutor,
       Map<MacroClass, Uri> precompiledMacroUris,
       Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData,
       MacroApplicationDataForTesting? dataForTesting) async {
-    Map<ClassBuilder, MacroClassIdentifier> classIdCache = {};
+    Map<ClassBuilder, macro.MacroClassIdentifier> classIdCache = {};
 
-    Map<MacroApplication, MacroInstanceIdentifier> instanceIdCache = {};
+    Map<MacroApplication, macro.MacroInstanceIdentifier> instanceIdCache = {};
 
     Future<void> ensureMacroClassIds(
         List<MacroApplication>? applications) async {
@@ -112,16 +114,16 @@
               application.classBuilder.library.importUri,
               application.classBuilder.name);
           Uri? precompiledMacroUri = precompiledMacroUris[macroClass];
-          MacroClassIdentifier macroClassIdentifier =
+          macro.MacroClassIdentifier macroClassIdentifier =
               classIdCache[application.classBuilder] ??= await macroExecutor
                   .loadMacro(macroClass.importUri, macroClass.className,
                       precompiledKernelUri: precompiledMacroUri);
-          application.instanceIdentifier = instanceIdCache[application] =
+          application.instanceIdentifier = instanceIdCache[application] ??=
               await macroExecutor.instantiateMacro(
                   macroClassIdentifier,
                   application.constructorName,
                   // TODO(johnniwinther): Support macro arguments.
-                  new Arguments([], {}));
+                  new macro.Arguments([], {}));
         }
       }
     }
@@ -161,17 +163,18 @@
     }
   }
 
-  Future<List<MacroExecutionResult>> _applyTypeMacros(
+  Future<List<macro.MacroExecutionResult>> _applyTypeMacros(
       macro.Declaration declaration,
       List<MacroApplication> macroApplications) async {
-    List<MacroExecutionResult> results = [];
+    List<macro.MacroExecutionResult> results = [];
     for (MacroApplication macroApplication in macroApplications) {
       if (macroApplication.instanceIdentifier.shouldExecute(
           // TODO(johnniwinther): Get the declaration kind from [declaration].
-          DeclarationKind.function,
-          Phase.types)) {
-        MacroExecutionResult result = await _macroExecutor.executeTypesPhase(
-            macroApplication.instanceIdentifier, declaration);
+          macro.DeclarationKind.function,
+          macro.Phase.types)) {
+        macro.MacroExecutionResult result =
+            await _macroExecutor.executeTypesPhase(
+                macroApplication.instanceIdentifier, declaration);
         results.add(result);
       }
     }
@@ -188,7 +191,7 @@
         MemberBuilder memberBuilder = memberEntry.key;
         macro.Declaration? declaration = _getMemberDeclaration(memberBuilder);
         if (declaration != null) {
-          List<MacroExecutionResult> results =
+          List<macro.MacroExecutionResult> results =
               await _applyTypeMacros(declaration, memberEntry.value);
           dataForTesting?.memberTypesResults[memberBuilder] = results;
         }
@@ -196,18 +199,18 @@
     }
   }
 
-  Future<List<MacroExecutionResult>> _applyDeclarationMacros(
+  Future<List<macro.MacroExecutionResult>> _applyDeclarationMacros(
       macro.Declaration declaration,
       List<MacroApplication> macroApplications,
       macro.TypeResolver typeResolver,
       macro.ClassIntrospector classIntrospector) async {
-    List<MacroExecutionResult> results = [];
+    List<macro.MacroExecutionResult> results = [];
     for (MacroApplication macroApplication in macroApplications) {
       if (macroApplication.instanceIdentifier.shouldExecute(
           // TODO(johnniwinther): Get the declaration kind from [declaration].
-          DeclarationKind.function,
-          Phase.declarations)) {
-        MacroExecutionResult result =
+          macro.DeclarationKind.function,
+          macro.Phase.declarations)) {
+        macro.MacroExecutionResult result =
             await _macroExecutor.executeDeclarationsPhase(
                 macroApplication.instanceIdentifier,
                 declaration,
@@ -219,9 +222,14 @@
     return results;
   }
 
-  Future<void> applyDeclarationMacros() async {
-    macro.TypeResolver typeResolver = new _TypeResolver(this);
-    macro.ClassIntrospector classIntrospector = new _ClassIntrospector();
+  late Types types;
+  late macro.TypeResolver typeResolver;
+  late macro.ClassIntrospector classIntrospector;
+
+  Future<void> applyDeclarationMacros(ClassHierarchyBase classHierarchy) async {
+    types = new Types(classHierarchy);
+    typeResolver = new _TypeResolver(this);
+    classIntrospector = new _ClassIntrospector();
     for (MapEntry<SourceLibraryBuilder,
         LibraryMacroApplicationData> libraryEntry in libraryData.entries) {
       LibraryMacroApplicationData libraryMacroApplicationData =
@@ -231,27 +239,28 @@
         MemberBuilder memberBuilder = memberEntry.key;
         macro.Declaration? declaration = _getMemberDeclaration(memberBuilder);
         if (declaration != null) {
-          List<MacroExecutionResult> results = await _applyDeclarationMacros(
-              declaration, memberEntry.value, typeResolver, classIntrospector);
+          List<macro.MacroExecutionResult> results =
+              await _applyDeclarationMacros(declaration, memberEntry.value,
+                  typeResolver, classIntrospector);
           dataForTesting?.memberDeclarationsResults[memberBuilder] = results;
         }
       }
     }
   }
 
-  Future<List<MacroExecutionResult>> _applyDefinitionMacros(
+  Future<List<macro.MacroExecutionResult>> _applyDefinitionMacros(
       macro.Declaration declaration,
       List<MacroApplication> macroApplications,
       macro.TypeResolver typeResolver,
       macro.ClassIntrospector classIntrospector,
       macro.TypeDeclarationResolver typeDeclarationResolver) async {
-    List<MacroExecutionResult> results = [];
+    List<macro.MacroExecutionResult> results = [];
     for (MacroApplication macroApplication in macroApplications) {
       if (macroApplication.instanceIdentifier.shouldExecute(
           // TODO(johnniwinther): Get the declaration kind from [declaration].
-          DeclarationKind.function,
-          Phase.definitions)) {
-        MacroExecutionResult result =
+          macro.DeclarationKind.function,
+          macro.Phase.definitions)) {
+        macro.MacroExecutionResult result =
             await _macroExecutor.executeDefinitionsPhase(
                 macroApplication.instanceIdentifier,
                 declaration,
@@ -264,13 +273,7 @@
     return results;
   }
 
-  late TypeEnvironment typeEnvironment;
-
-  Future<void> applyDefinitionMacros(
-      CoreTypes coreTypes, ClassHierarchy classHierarchy) async {
-    typeEnvironment = new TypeEnvironment(coreTypes, classHierarchy);
-    macro.TypeResolver typeResolver = new _TypeResolver(this);
-    macro.ClassIntrospector classIntrospector = new _ClassIntrospector();
+  Future<void> applyDefinitionMacros() async {
     macro.TypeDeclarationResolver typeDeclarationResolver =
         new _TypeDeclarationResolver();
     for (MapEntry<SourceLibraryBuilder,
@@ -282,12 +285,9 @@
         MemberBuilder memberBuilder = memberEntry.key;
         macro.Declaration? declaration = _getMemberDeclaration(memberBuilder);
         if (declaration != null) {
-          List<MacroExecutionResult> results = await _applyDefinitionMacros(
-              declaration,
-              memberEntry.value,
-              typeResolver,
-              classIntrospector,
-              typeDeclarationResolver);
+          List<macro.MacroExecutionResult> results =
+              await _applyDefinitionMacros(declaration, memberEntry.value,
+                  typeResolver, classIntrospector, typeDeclarationResolver);
           dataForTesting?.memberDefinitionsResults[memberBuilder] = results;
         }
       }
@@ -302,8 +302,8 @@
 
   macro.FunctionDeclaration createTopLevelFunctionDeclaration(
       SourceProcedureBuilder builder) {
-    List<ParameterDeclarationImpl>? positionalParameters;
-    List<ParameterDeclarationImpl>? namedParameters;
+    List<macro.ParameterDeclarationImpl>? positionalParameters;
+    List<macro.ParameterDeclarationImpl>? namedParameters;
 
     List<FormalParameterBuilder>? formals = builder.formals;
     if (formals == null) {
@@ -312,23 +312,23 @@
       positionalParameters = [];
       namedParameters = [];
       for (FormalParameterBuilder formal in formals) {
-        TypeAnnotationImpl type =
+        macro.TypeAnnotationImpl type =
             computeTypeAnnotation(builder.library, formal.type);
         // TODO(johnniwinther): Support default values.
         if (formal.isNamed) {
-          namedParameters.add(new ParameterDeclarationImpl(
-              id: RemoteInstance.uniqueId,
-              identifier: new IdentifierImpl(
-                  id: RemoteInstance.uniqueId, name: formal.name),
+          namedParameters.add(new macro.ParameterDeclarationImpl(
+              id: macro.RemoteInstance.uniqueId,
+              identifier: new macro.IdentifierImpl(
+                  id: macro.RemoteInstance.uniqueId, name: formal.name),
               isRequired: formal.isNamedRequired,
               isNamed: true,
               type: type,
               defaultValue: null));
         } else {
-          positionalParameters.add(new ParameterDeclarationImpl(
-              id: RemoteInstance.uniqueId,
-              identifier: new IdentifierImpl(
-                  id: RemoteInstance.uniqueId, name: formal.name),
+          positionalParameters.add(new macro.ParameterDeclarationImpl(
+              id: macro.RemoteInstance.uniqueId,
+              identifier: new macro.IdentifierImpl(
+                  id: macro.RemoteInstance.uniqueId, name: formal.name),
               isRequired: formal.isRequired,
               isNamed: false,
               type: type,
@@ -337,10 +337,10 @@
       }
     }
 
-    return new FunctionDeclarationImpl(
-        id: RemoteInstance.uniqueId,
-        identifier:
-            new IdentifierImpl(id: RemoteInstance.uniqueId, name: builder.name),
+    return new macro.FunctionDeclarationImpl(
+        id: macro.RemoteInstance.uniqueId,
+        identifier: new macro.IdentifierImpl(
+            id: macro.RemoteInstance.uniqueId, name: builder.name),
         isAbstract: builder.isAbstract,
         isExternal: builder.isExternal,
         isGetter: builder.isGetter,
@@ -354,7 +354,7 @@
 
   Map<TypeBuilder?, _NamedTypeAnnotationImpl> _typeAnnotationCache = {};
 
-  List<TypeAnnotationImpl> computeTypeAnnotations(
+  List<macro.TypeAnnotationImpl> computeTypeAnnotations(
       LibraryBuilder library, List<TypeBuilder>? typeBuilders) {
     if (typeBuilders == null) return const [];
     return new List.generate(typeBuilders.length,
@@ -366,16 +366,16 @@
     if (typeBuilder != null) {
       if (typeBuilder is NamedTypeBuilder) {
         Object name = typeBuilder.name;
-        List<TypeAnnotationImpl> typeArguments =
+        List<macro.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,
-              identifier:
-                  new IdentifierImpl(id: RemoteInstance.uniqueId, name: name),
+              id: macro.RemoteInstance.uniqueId,
+              identifier: new macro.IdentifierImpl(
+                  id: macro.RemoteInstance.uniqueId, name: name),
               typeArguments: typeArguments,
               isNullable: isNullable);
         } else if (name is QualifiedName) {
@@ -383,9 +383,9 @@
           return new _NamedTypeAnnotationImpl(
               typeBuilder: typeBuilder,
               libraryBuilder: libraryBuilder,
-              id: RemoteInstance.uniqueId,
-              identifier: new IdentifierImpl(
-                  id: RemoteInstance.uniqueId,
+              id: macro.RemoteInstance.uniqueId,
+              identifier: new macro.IdentifierImpl(
+                  id: macro.RemoteInstance.uniqueId,
                   // TODO: We probably shouldn't be including the qualifier
                   // here. Kernel should probably have its own implementation
                   // of Identifier which holds on to the qualified reference
@@ -399,13 +399,13 @@
     return new _NamedTypeAnnotationImpl(
         typeBuilder: typeBuilder,
         libraryBuilder: libraryBuilder,
-        id: RemoteInstance.uniqueId,
+        id: macro.RemoteInstance.uniqueId,
         identifier: dynamicIdentifier,
         isNullable: false,
         typeArguments: const []);
   }
 
-  TypeAnnotationImpl computeTypeAnnotation(
+  macro.TypeAnnotationImpl computeTypeAnnotation(
       LibraryBuilder libraryBuilder, TypeBuilder? typeBuilder) {
     return _typeAnnotationCache[typeBuilder] ??=
         _computeTypeAnnotation(libraryBuilder, typeBuilder);
@@ -431,7 +431,7 @@
   }
 }
 
-class _NamedTypeAnnotationImpl extends NamedTypeAnnotationImpl {
+class _NamedTypeAnnotationImpl extends macro.NamedTypeAnnotationImpl {
   final TypeBuilder? typeBuilder;
   final LibraryBuilder libraryBuilder;
 
@@ -440,8 +440,8 @@
     required this.libraryBuilder,
     required int id,
     required bool isNullable,
-    required IdentifierImpl identifier,
-    required List<TypeAnnotationImpl> typeArguments,
+    required macro.IdentifierImpl identifier,
+    required List<macro.TypeAnnotationImpl> typeArguments,
   }) : super(
             id: id,
             isNullable: isNullable,
@@ -462,7 +462,7 @@
 
   @override
   Future<bool> isSubtypeOf(covariant _StaticTypeImpl other) {
-    return new Future.value(macroApplications.typeEnvironment
+    return new Future.value(macroApplications.types
         .isSubtypeOf(type, other.type, SubtypeCheckMode.withNullabilities));
   }
 }
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 4979c76..ff31d86 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
@@ -56,3 +56,23 @@
 '''));
   }
 }
+
+macro class FunctionDeclarationsMacro2 implements FunctionDeclarationsMacro {
+  const FunctionDeclarationsMacro2();
+
+  FutureOr<void> buildDeclarationsForFunction(
+      FunctionDeclaration function, DeclarationBuilder builder) async {
+    if (function.positionalParameters.isEmpty) {
+      return;
+    }
+    StaticType returnType = await builder.instantiateType(function.returnType);
+    StaticType parameterType =
+        await builder.instantiateType(function.positionalParameters.first.type);
+    bool isExactly = await returnType.isExactly(parameterType);
+    bool isSubtype = await returnType.isSubtypeOf(parameterType);
+    String tag = '${isExactly ? 'e' : ''}${isSubtype ? 's' : ''}';
+    builder.declareInLibrary(new DeclarationCode.fromString('''
+void ${function.identifier.name}GeneratedMethod_$tag() {}
+'''));
+  }
+}
diff --git a/pkg/front_end/test/macro_application/data/tests/subtypes.dart b/pkg/front_end/test/macro_application/data/tests/subtypes.dart
index 245908a..4340fc2 100644
--- a/pkg/front_end/test/macro_application/data/tests/subtypes.dart
+++ b/pkg/front_end/test/macro_application/data/tests/subtypes.dart
@@ -19,33 +19,45 @@
 class D2 {}
 
 /*member: topLevelFunction1:
+void topLevelFunction1GeneratedMethod_es() {}
+
 augment A topLevelFunction1(A a, ) {
   print('isExactly=true');
   print('isSubtype=true');
 }*/
+@FunctionDeclarationsMacro2()
 @FunctionDefinitionMacro2()
 external A topLevelFunction1(A a);
 
 /*member: topLevelFunction2:
+void topLevelFunction2GeneratedMethod_s() {}
+
 augment B2 topLevelFunction2(B1 a, ) {
   print('isExactly=false');
   print('isSubtype=true');
 }*/
+@FunctionDeclarationsMacro2()
 @FunctionDefinitionMacro2()
 external B2 topLevelFunction2(B1 a);
 
 /*member: topLevelFunction3:
+void topLevelFunction3GeneratedMethod_() {}
+
 augment C2 topLevelFunction3(C1 a, ) {
   print('isExactly=false');
   print('isSubtype=false');
 }*/
+@FunctionDeclarationsMacro2()
 @FunctionDefinitionMacro2()
 external C2 topLevelFunction3(C1 a);
 
 /*member: topLevelFunction4:
+void topLevelFunction4GeneratedMethod_() {}
+
 augment D2 topLevelFunction4(D1 a, ) {
   print('isExactly=false');
   print('isSubtype=false');
 }*/
+@FunctionDeclarationsMacro2()
 @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 0ad035b..45ae3a5 100644
--- a/pkg/front_end/test/macro_application/macro_application_test.dart
+++ b/pkg/front_end/test/macro_application/macro_application_test.dart
@@ -31,6 +31,7 @@
     'FunctionDefinitionMacro2': [''],
     'FunctionTypesMacro1': [''],
     'FunctionDeclarationsMacro1': [''],
+    'FunctionDeclarationsMacro2': [''],
   }
 };
 
diff --git a/pkg/front_end/test/macros/macro_test.dart b/pkg/front_end/test/macros/macro_test.dart
index 47c4300..1bedb08 100644
--- a/pkg/front_end/test/macros/macro_test.dart
+++ b/pkg/front_end/test/macros/macro_test.dart
@@ -126,6 +126,7 @@
 
   MacroDeclarationData get macroDeclarationData => testResultData.compilerResult
       .kernelTargetForTesting!.loader.dataForTesting!.macroDeclarationData;
+
   MacroApplicationDataForTesting get macroApplicationData => testResultData
       .compilerResult
       .kernelTargetForTesting!
@@ -280,8 +281,8 @@
   List<_MacroInstanceIdentifier> macroInstances = [];
 
   @override
-  Future<String> buildAugmentationLibrary(
-      Iterable<MacroExecutionResult> macroResults) {
+  String buildAugmentationLibrary(Iterable<MacroExecutionResult> macroResults,
+      Uri Function(Identifier) resolveIdentifier) {
     // TODO: implement buildAugmentationLibrary
     throw UnimplementedError();
   }
@@ -386,8 +387,5 @@
   Iterable<DeclarationCode> augmentations = const [];
 
   @override
-  Iterable<DeclarationCode> imports = const [];
-
-  @override
   void serialize(Serializer serializer) {}
 }
diff --git a/tools/VERSION b/tools/VERSION
index 6acbdae75..d2fe2b3 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 17
 PATCH 0
-PRERELEASE 70
+PRERELEASE 71
 PRERELEASE_PATCH 0
\ No newline at end of file