Version 2.18.0-12.0.dev

Merge commit 'b7257ef58ee7323cade1b4f3bd1ca19658d89415' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/lib/src/deferred_closure_heuristic.dart b/pkg/_fe_analyzer_shared/lib/src/deferred_closure_heuristic.dart
index d5f823a..9bff8c0 100644
--- a/pkg/_fe_analyzer_shared/lib/src/deferred_closure_heuristic.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/deferred_closure_heuristic.dart
@@ -4,136 +4,163 @@
 
 import 'package:_fe_analyzer_shared/src/util/dependency_walker.dart';
 
-/// Data structure tracking the type inference dependencies between closures
-/// passed as invocation parameters.
+/// Data structure tracking the type inference dependencies between generic
+/// invocation parameters.
 ///
-/// [planClosureReconciliationStages] is used as part of support for
+/// [planReconciliationStages] is used as part of support for
 /// https://github.com/dart-lang/language/issues/731 (improved inference for
 /// fold etc.) to choose the proper order in which to recursively analyze
 /// closures passed as invocation arguments.
-abstract class ClosureDependencies<TypeVariable, Closure> {
-  final List<_ClosureNode<Closure>> _closureNodes = [];
+abstract class ClosureDependencies<TypeVariable, ParamInfo,
+    DeferredParamInfo extends ParamInfo> {
+  final List<_Node<ParamInfo>> _paramNodes = [];
 
   /// Construct a [ClosureDependencies] object that's prepared to determine the
-  /// order to resolve [closures] for a generic invocation involving the given
-  /// [typeVariables].
+  /// order to resolve [deferredParams] for a generic invocation involving the
+  /// given [typeVariables].
+  ///
+  /// [unDeferredParams] should contain information about any parameters
+  /// corresponding to arguments that have already been type inferred.
   ClosureDependencies(
-      Iterable<Closure> closures, Iterable<TypeVariable> typeVariables) {
-    Map<TypeVariable, Set<_ClosureNode<Closure>>> closuresDependingOnTypeVar =
-        {};
-    Map<TypeVariable, Set<_ClosureNode<Closure>>> closuresConstrainingTypeVar =
-        {};
-    for (Closure closure in closures) {
-      _ClosureNode<Closure> closureNode = new _ClosureNode<Closure>(closure);
-      _closureNodes.add(closureNode);
-      for (TypeVariable v in typeVarsFreeInClosureArguments(closure)) {
-        (closuresDependingOnTypeVar[v] ??= {}).add(closureNode);
+      Iterable<DeferredParamInfo> deferredParams,
+      Iterable<TypeVariable> typeVariables,
+      Iterable<ParamInfo> unDeferredParams) {
+    Map<TypeVariable, Set<_Node<ParamInfo>>> paramsDependingOnTypeVar = {};
+    Map<TypeVariable, Set<_Node<ParamInfo>>> paramsConstrainingTypeVar = {};
+    for (DeferredParamInfo param in deferredParams) {
+      _Node<ParamInfo> paramNode =
+          new _Node<ParamInfo>(param, isDeferred: true);
+      _paramNodes.add(paramNode);
+      for (TypeVariable v in typeVarsFreeInParamParams(param)) {
+        (paramsDependingOnTypeVar[v] ??= {}).add(paramNode);
       }
-      for (TypeVariable v in typeVarsFreeInClosureReturns(closure)) {
-        (closuresConstrainingTypeVar[v] ??= {}).add(closureNode);
+      for (TypeVariable v in typeVarsFreeInParamReturns(param)) {
+        (paramsConstrainingTypeVar[v] ??= {}).add(paramNode);
+      }
+    }
+    for (ParamInfo param in unDeferredParams) {
+      _Node<ParamInfo> paramNode =
+          new _Node<ParamInfo>(param, isDeferred: false);
+      _paramNodes.add(paramNode);
+      // Note: for un-deferred parameters, we only care about
+      // typeVarsFreeInParamReturns, because these parameters have already been
+      // analyzed, so they can't depend on other parameters.
+      for (TypeVariable v in typeVarsFreeInParamReturns(param)) {
+        (paramsConstrainingTypeVar[v] ??= {}).add(paramNode);
       }
     }
     for (TypeVariable typeVariable in typeVariables) {
-      for (_ClosureNode<Closure> closureNode
-          in closuresDependingOnTypeVar[typeVariable] ?? const {}) {
-        closureNode.dependencies
-            .addAll(closuresConstrainingTypeVar[typeVariable] ?? const {});
+      for (_Node<ParamInfo> paramNode
+          in paramsDependingOnTypeVar[typeVariable] ?? const {}) {
+        paramNode.dependencies
+            .addAll(paramsConstrainingTypeVar[typeVariable] ?? const {});
       }
     }
   }
 
-  /// Computes the order in which to resolve the closures passed to the
-  /// constructor.
+  /// Computes the order in which to resolve the deferred parameters passed to
+  /// the constructor.
   ///
-  /// Each entry in the returned list represents the set of closures that should
-  /// be visited during a single stage of resolution; after each stage, the
-  /// assignment of actual types to type variables should be refined.
+  /// Each entry in the returned list represents the set of parameters whose
+  /// corresponding arguments should be visited during a single stage of
+  /// resolution; after each stage, the assignment of actual types to type
+  /// variables should be refined.
   ///
-  /// So, for example, if the closures in question are A, B, and C, and the
-  /// returned list is `[{A, B}, {C}]`, then first closures A and B should be
+  /// So, for example, if the parameters in question are A, B, and C, and the
+  /// returned list is `[{A, B}, {C}]`, then first parameters A and B should be
   /// resolved, then the assignment of actual types to type variables should be
   /// refined, and then C should be resolved, and then the final assignment of
   /// actual types to type variables should be computed.
-  List<Set<Closure>> planClosureReconciliationStages() {
-    _DependencyWalker<Closure> walker = new _DependencyWalker<Closure>();
-    for (_ClosureNode<Closure> closureNode in _closureNodes) {
-      walker.walk(closureNode);
+  ///
+  /// Note that the first stage may be empty; when this happens, it means that
+  /// the assignment of actual types to type variables should be refined before
+  /// doing any visiting.
+  List<Set<DeferredParamInfo>> planReconciliationStages() {
+    _DependencyWalker<ParamInfo, DeferredParamInfo> walker =
+        new _DependencyWalker<ParamInfo, DeferredParamInfo>();
+    for (_Node<ParamInfo> paramNode in _paramNodes) {
+      walker.walk(paramNode);
     }
-    return walker.closureReconciliationStages;
+    return walker.reconciliationStages;
   }
 
-  /// If the type of the parameter corresponding to [closure] is a function
-  /// type, the set of type parameters referred to by the parameter types of
-  /// that parameter.  If the type of the parameter is not a function type, an
-  /// empty iterable should be returned.
+  /// If the type of the parameter corresponding to [param] is a function type,
+  /// the set of type parameters referred to by the parameter types of that
+  /// parameter.  If the type of the parameter is not a function type, an empty
+  /// iterable should be returned.
   ///
   /// Should be overridden by the client.
-  Iterable<TypeVariable> typeVarsFreeInClosureArguments(Closure closure);
+  Iterable<TypeVariable> typeVarsFreeInParamParams(DeferredParamInfo param);
 
-  /// If the type of the parameter corresponding to [closure] is a function
-  /// type, the set of type parameters referred to by the return type of that
+  /// If the type of the parameter corresponding to [param] is a function type,
+  /// the set of type parameters referred to by the return type of that
   /// parameter.  If the type of the parameter is not a function type, the set
   /// type parameters referred to by the type of the parameter should be
   /// returned.
   ///
   /// Should be overridden by the client.
-  Iterable<TypeVariable> typeVarsFreeInClosureReturns(Closure closure);
-}
-
-/// Node type representing a single [Closure] for purposes of walking the
-/// graph of type inference dependencies among closures.
-class _ClosureNode<Closure> extends Node<_ClosureNode<Closure>> {
-  /// The [Closure] being represented by this node.
-  final Closure closure;
-
-  /// If not `null`, the index of the reconciliation stage to which this closure
-  /// has been assigned.
-  int? stageNum;
-
-  /// The nodes for the closures depended on by this closure.
-  final List<_ClosureNode<Closure>> dependencies = [];
-
-  _ClosureNode(this.closure);
-
-  @override
-  bool get isEvaluated => stageNum != null;
-
-  @override
-  List<_ClosureNode<Closure>> computeDependencies() => dependencies;
+  Iterable<TypeVariable> typeVarsFreeInParamReturns(ParamInfo param);
 }
 
 /// Derived class of [DependencyWalker] capable of walking the graph of type
-/// inference dependencies among closures.
-class _DependencyWalker<Closure>
-    extends DependencyWalker<_ClosureNode<Closure>> {
-  /// The set of closure reconciliation stages accumulated so far.
-  final List<Set<Closure>> closureReconciliationStages = [];
+/// inference dependencies among parameters.
+class _DependencyWalker<ParamInfo, DeferredParamInfo extends ParamInfo>
+    extends DependencyWalker<_Node<ParamInfo>> {
+  /// The set of reconciliation stages accumulated so far.
+  final List<Set<DeferredParamInfo>> reconciliationStages = [];
 
   @override
-  void evaluate(_ClosureNode v) => evaluateScc([v]);
+  void evaluate(_Node<ParamInfo> v) => evaluateScc([v]);
 
   @override
-  void evaluateScc(List<_ClosureNode> nodes) {
+  void evaluateScc(List<_Node<ParamInfo>> nodes) {
     int stageNum = 0;
-    for (_ClosureNode node in nodes) {
-      for (_ClosureNode dependency in node.dependencies) {
+    for (_Node<ParamInfo> node in nodes) {
+      for (_Node<ParamInfo> dependency in node.dependencies) {
         int? dependencyStageNum = dependency.stageNum;
         if (dependencyStageNum != null && dependencyStageNum >= stageNum) {
           stageNum = dependencyStageNum + 1;
         }
       }
     }
-    if (closureReconciliationStages.length <= stageNum) {
-      closureReconciliationStages.add({});
+    if (reconciliationStages.length <= stageNum) {
+      reconciliationStages.add({});
       // `stageNum` can't grow by more than 1 each time `evaluateScc` is called,
       // so adding one stage is sufficient to make sure the list is now long
       // enough.
-      assert(stageNum < closureReconciliationStages.length);
+      assert(stageNum < reconciliationStages.length);
     }
-    Set<Closure> stage = closureReconciliationStages[stageNum];
-    for (_ClosureNode node in nodes) {
+    Set<DeferredParamInfo> stage = reconciliationStages[stageNum];
+    for (_Node<ParamInfo> node in nodes) {
       node.stageNum = stageNum;
-      stage.add(node.closure);
+      if (node.isDeferred) {
+        stage.add(node.param as DeferredParamInfo);
+      }
     }
   }
 }
+
+/// Node type representing a single parameter for purposes of walking the graph
+/// of type inference dependencies among parameters.
+class _Node<ParamInfo> extends Node<_Node<ParamInfo>> {
+  /// The [ParamInfo] represented by this node.
+  final ParamInfo param;
+
+  /// If not `null`, the index of the reconciliation stage to which this
+  /// parameter has been assigned.
+  int? stageNum;
+
+  /// The nodes for the parameters depended on by this parameter.
+  final List<_Node<ParamInfo>> dependencies = [];
+
+  /// Indicates whether this node represents a deferred parameter.
+  final bool isDeferred;
+
+  _Node(this.param, {required this.isDeferred});
+
+  @override
+  bool get isEvaluated => stageNum != null;
+
+  @override
+  List<_Node<ParamInfo>> computeDependencies() => dependencies;
+}
diff --git a/pkg/_fe_analyzer_shared/test/deferred_closure_heuristic_test.dart b/pkg/_fe_analyzer_shared/test/deferred_closure_heuristic_test.dart
index ab4b8f9..41ec79e 100644
--- a/pkg/_fe_analyzer_shared/test/deferred_closure_heuristic_test.dart
+++ b/pkg/_fe_analyzer_shared/test/deferred_closure_heuristic_test.dart
@@ -8,10 +8,10 @@
 main() {
   test('single', () {
     // If there is just a single closure and no type variables, it is selected.
-    var f = Closure('f');
+    var f = Param('f');
     expect(
         _TestClosureDeps(typeVars: [], closures: [f])
-            .planClosureReconciliationStages(),
+            .planReconciliationStages(),
         [
           {f}
         ]);
@@ -19,11 +19,11 @@
 
   test('simple dependency', () {
     // If f depends on g, then g is selected first, and then f.
-    var f = Closure('f', argTypes: ['T']);
-    var g = Closure('g', retTypes: ['T']);
+    var f = Param('f', argTypes: ['T']);
+    var g = Param('g', retTypes: ['T']);
     expect(
         _TestClosureDeps(typeVars: ['T'], closures: [f, g])
-            .planClosureReconciliationStages(),
+            .planReconciliationStages(),
         [
           {g},
           {f}
@@ -33,12 +33,12 @@
   test('long chain', () {
     // If f depends on g and g depends on h, then we do three separate stages:
     // h, then g, then f.
-    var f = Closure('f', argTypes: ['T']);
-    var g = Closure('g', argTypes: ['U'], retTypes: ['T']);
-    var h = Closure('h', retTypes: ['U']);
+    var f = Param('f', argTypes: ['T']);
+    var g = Param('g', argTypes: ['U'], retTypes: ['T']);
+    var h = Param('h', retTypes: ['U']);
     expect(
         _TestClosureDeps(typeVars: ['T', 'U'], closures: [f, g, h])
-            .planClosureReconciliationStages(),
+            .planReconciliationStages(),
         [
           {h},
           {g},
@@ -49,12 +49,12 @@
   test('unrelated closure', () {
     // Closures that are independent of all the others are inferred during the
     // first stage.
-    var f = Closure('f', argTypes: ['T']);
-    var g = Closure('g', retTypes: ['T']);
-    var h = Closure('h');
+    var f = Param('f', argTypes: ['T']);
+    var g = Param('g', retTypes: ['T']);
+    var h = Param('h');
     expect(
         _TestClosureDeps(typeVars: ['T', 'U'], closures: [f, g, h])
-            .planClosureReconciliationStages(),
+            .planReconciliationStages(),
         [
           {g, h},
           {f}
@@ -64,13 +64,13 @@
   test('independent chains', () {
     // If f depends on g, and h depends on i, then g and i are selected first,
     // and then f and h.
-    var f = Closure('f', argTypes: ['T']);
-    var g = Closure('g', retTypes: ['T']);
-    var h = Closure('h', argTypes: ['U']);
-    var i = Closure('i', retTypes: ['U']);
+    var f = Param('f', argTypes: ['T']);
+    var g = Param('g', retTypes: ['T']);
+    var h = Param('h', argTypes: ['U']);
+    var i = Param('i', retTypes: ['U']);
     expect(
         _TestClosureDeps(typeVars: ['T', 'U'], closures: [f, g, h, i])
-            .planClosureReconciliationStages(),
+            .planReconciliationStages(),
         [
           {g, i},
           {f, h}
@@ -80,13 +80,13 @@
   test('diamond', () {
     // Test a diamond dependency shape: f depends on g and h; g and h both
     // depend on i.
-    var f = Closure('f', argTypes: ['T', 'U']);
-    var g = Closure('g', argTypes: ['V'], retTypes: ['T']);
-    var h = Closure('h', argTypes: ['V'], retTypes: ['U']);
-    var i = Closure('i', retTypes: ['V']);
+    var f = Param('f', argTypes: ['T', 'U']);
+    var g = Param('g', argTypes: ['V'], retTypes: ['T']);
+    var h = Param('h', argTypes: ['V'], retTypes: ['U']);
+    var i = Param('i', retTypes: ['V']);
     expect(
         _TestClosureDeps(typeVars: ['T', 'U', 'V'], closures: [f, g, h, i])
-            .planClosureReconciliationStages(),
+            .planReconciliationStages(),
         [
           {i},
           {g, h},
@@ -96,43 +96,59 @@
 
   test('cycle', () {
     // A dependency cycle is inferred all at once.
-    var f = Closure('f', argTypes: ['T']);
-    var g = Closure('g', argTypes: ['U']);
-    var h = Closure('h', argTypes: ['U'], retTypes: ['T']);
-    var i = Closure('i', argTypes: ['T'], retTypes: ['U']);
+    var f = Param('f', argTypes: ['T']);
+    var g = Param('g', argTypes: ['U']);
+    var h = Param('h', argTypes: ['U'], retTypes: ['T']);
+    var i = Param('i', argTypes: ['T'], retTypes: ['U']);
     expect(
         _TestClosureDeps(typeVars: ['T', 'U'], closures: [f, g, h, i])
-            .planClosureReconciliationStages(),
+            .planReconciliationStages(),
         [
           {h, i},
           {f, g}
         ]);
   });
+
+  test('dependency on undeferred param', () {
+    var f = Param('f', argTypes: ['T']);
+    var x = Param('x', retTypes: ['T']);
+    expect(
+        _TestClosureDeps(typeVars: ['T'], closures: [f], undeferredParams: [x])
+            .planReconciliationStages(),
+        [
+          <Param>{},
+          {f}
+        ]);
+  });
 }
 
-class Closure {
+class Param {
   final String name;
   final List<String> argTypes;
   final List<String> retTypes;
 
-  Closure(this.name, {this.argTypes = const [], this.retTypes = const []});
+  Param(this.name, {this.argTypes = const [], this.retTypes = const []});
 
   @override
   String toString() => name;
 }
 
-class _TestClosureDeps extends ClosureDependencies<String, Closure> {
+class _TestClosureDeps extends ClosureDependencies<String, Param, Param> {
   final List<String> typeVars;
-  final List<Closure> closures;
+  final List<Param> closures;
+  final List<Param> undeferredParams;
 
-  _TestClosureDeps({required this.typeVars, required this.closures})
-      : super(closures, typeVars);
+  _TestClosureDeps(
+      {required this.typeVars,
+      required this.closures,
+      this.undeferredParams = const []})
+      : super(closures, typeVars, undeferredParams);
 
   @override
-  Set<String> typeVarsFreeInClosureArguments(Closure closure) =>
+  Set<String> typeVarsFreeInParamParams(Param closure) =>
       closure.argTypes.toSet();
 
   @override
-  Set<String> typeVarsFreeInClosureReturns(Closure closure) =>
+  Set<String> typeVarsFreeInParamReturns(Param closure) =>
       closure.retTypes.toSet();
 }
diff --git a/pkg/analysis_server/lib/src/plugin/plugin_manager.dart b/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
index ae25ec1..7dc3e98 100644
--- a/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
+++ b/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
@@ -632,13 +632,8 @@
         .getChildAssumingFolder(file_paths.dotDartTool)
         .getChildAssumingFile(file_paths.packageConfigJson);
     if (pubCommand != null) {
-      var vmPath = Platform.executable;
-      var pubPath = path.join(path.dirname(vmPath), 'pub');
-      if (Platform.isWindows) {
-        // Process.run requires the `.bat` suffix on Windows
-        pubPath = '$pubPath.bat';
-      }
-      var result = Process.runSync(pubPath, <String>[pubCommand],
+      var result = Process.runSync(
+          Platform.executable, <String>['pub', pubCommand],
           stderrEncoding: utf8,
           stdoutEncoding: utf8,
           workingDirectory: pluginFolder.path,
diff --git a/pkg/analyzer/analysis_options.yaml b/pkg/analyzer/analysis_options.yaml
index 1d8a622..876098b 100644
--- a/pkg/analyzer/analysis_options.yaml
+++ b/pkg/analyzer/analysis_options.yaml
@@ -1,16 +1,9 @@
-include: package:pedantic/analysis_options.1.9.0.yaml
+include: package:lints/recommended.yaml
 
 analyzer:
   errors:
     # Increase the severity of the unused_import hint.
     unused_import: warning
-    # There are currently 10k violations in test/ and tool/.
-    always_declare_return_types: ignore
-    # There are currently 5000 violations in lib/. This just does not fit well
-    # with the analyzer team's style.
-    omit_local_variable_types: ignore
-    # There are currently 3360 violations in lib/.
-    prefer_single_quotes: ignore
 
     # "strict-inference" is enabled, but "unused" parameters named '_' are
     # still reported.  Re-evaluate after
@@ -21,6 +14,19 @@
     # "ignored for test/**/*.dart".
     inference_failure_on_function_return_type: ignore
 
+    # Lints from the recommended set that conflict w/ analyzer style or will
+    # require some work to reach compliance.
+    # See: https://github.com/dart-lang/sdk/issues/48784
+    avoid_renaming_method_parameters: ignore
+    camel_case_types: ignore
+    constant_identifier_names: ignore
+    hash_and_equals: ignore
+    non_constant_identifier_names: ignore
+    implementation_imports: ignore
+    library_private_types_in_public_api: ignore
+    overridden_fields: ignore
+    provide_deprecation_message: ignore
+
   language:
     strict-inference: true
 
@@ -31,10 +37,4 @@
     - avoid_unused_constructor_parameters
     - await_only_futures
     - depend_on_referenced_packages
-    - empty_statements
-    - iterable_contains_unrelated_type
-    - list_remove_unrelated_type
-    - prefer_typing_uninitialized_variables
-    - unnecessary_brace_in_string_interps
-    - unnecessary_overrides
     - unnecessary_parenthesis
diff --git a/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart b/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart
index 266ad41..e7ff31d 100644
--- a/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart
@@ -2,6 +2,8 @@
 // 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/multi_executor.dart'
+    as macro;
 import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
 import 'package:analyzer/dart/analysis/context_locator.dart';
 import 'package:analyzer/dart/analysis/declared_variables.dart';
@@ -22,6 +24,9 @@
   /// The resource provider used to access the file system.
   final ResourceProvider resourceProvider;
 
+  /// The instance of macro executor that is used for all macros.
+  final macro.MultiMacroExecutor? macroExecutor = macro.MultiMacroExecutor();
+
   /// The list of analysis contexts.
   @override
   final List<DriverBasedAnalysisContext> contexts = [];
@@ -77,6 +82,7 @@
         updateAnalysisOptions: updateAnalysisOptions,
         fileContentCache: fileContentCache,
         macroKernelBuilder: macroKernelBuilder,
+        macroExecutor: macroExecutor,
       );
       contexts.add(context);
     }
@@ -109,6 +115,13 @@
     throw StateError('Unable to find the context to $path');
   }
 
+  void dispose() {
+    for (var analysisContext in contexts) {
+      analysisContext.driver.dispose();
+    }
+    macroExecutor?.close();
+  }
+
   /// Check every element with [_throwIfNotAbsoluteNormalizedPath].
   void _throwIfAnyNotAbsoluteNormalizedPath(List<String> paths) {
     for (var path in paths) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
index ddb9cc9..c1185f2 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
@@ -2,6 +2,8 @@
 // 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/multi_executor.dart'
+    as macro;
 import 'package:analyzer/dart/analysis/context_builder.dart';
 import 'package:analyzer/dart/analysis/context_root.dart';
 import 'package:analyzer/dart/analysis/declared_variables.dart';
@@ -60,6 +62,7 @@
     void Function(AnalysisOptionsImpl)? updateAnalysisOptions,
     FileContentCache? fileContentCache,
     MacroKernelBuilder? macroKernelBuilder,
+    macro.MultiMacroExecutor? macroExecutor,
   }) {
     // TODO(scheglov) Remove this, and make `sdkPath` required.
     sdkPath ??= getSdkPath();
@@ -118,6 +121,7 @@
       retainDataForTesting: retainDataForTesting,
       fileContentCache: fileContentCache,
       macroKernelBuilder: macroKernelBuilder,
+      macroExecutor: macroExecutor,
     );
 
     if (declaredVariables != null) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 457e79d..5e40995 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -5,6 +5,8 @@
 import 'dart:async';
 import 'dart:typed_data';
 
+import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart'
+    as macro;
 import 'package:analyzer/dart/analysis/analysis_context.dart' as api;
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/analysis/results.dart';
@@ -124,6 +126,9 @@
 
   final MacroKernelBuilder? macroKernelBuilder;
 
+  /// The instance of macro executor that is used for all macros.
+  final macro.MultiMacroExecutor? macroExecutor;
+
   /// The declared environment variables.
   DeclaredVariables declaredVariables = DeclaredVariables();
 
@@ -258,6 +263,7 @@
     required AnalysisOptionsImpl analysisOptions,
     required Packages packages,
     this.macroKernelBuilder,
+    this.macroExecutor,
     FileContentCache? fileContentCache,
     this.enableIndex = false,
     SummaryDataStore? externalSummaries,
@@ -325,6 +331,7 @@
       declaredVariables: declaredVariables,
       sourceFactory: _sourceFactory,
       macroKernelBuilder: macroKernelBuilder,
+      macroExecutor: macroExecutor,
       externalSummaries: _externalSummaries,
       fileSystemState: _fsState,
     );
@@ -525,6 +532,7 @@
   /// periodically.
   @visibleForTesting
   void clearLibraryContext() {
+    _libraryContext?.dispose();
     _libraryContext = null;
   }
 
@@ -578,6 +586,7 @@
   @override
   void dispose() {
     _scheduler.remove(this);
+    clearLibraryContext();
   }
 
   /// Return the cached [ResolvedUnitResult] for the Dart file with the given
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index 96dcbb7..57da9e4 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -4,6 +4,8 @@
 
 import 'dart:typed_data';
 
+import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart'
+    as macro;
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/element/element.dart'
     show CompilationUnitElement, LibraryElement;
@@ -43,6 +45,7 @@
   final ByteStore byteStore;
   final FileSystemState fileSystemState;
   final MacroKernelBuilder? macroKernelBuilder;
+  final macro.MultiMacroExecutor? macroExecutor;
   final SummaryDataStore store = SummaryDataStore();
 
   late final AnalysisContextImpl analysisContext;
@@ -57,7 +60,8 @@
     required AnalysisOptionsImpl analysisOptions,
     required DeclaredVariables declaredVariables,
     required SourceFactory sourceFactory,
-    this.macroKernelBuilder,
+    required this.macroKernelBuilder,
+    required this.macroExecutor,
     required SummaryDataStore? externalSummaries,
   }) {
     var synchronousSession =
@@ -92,6 +96,10 @@
     return element as CompilationUnitElement;
   }
 
+  void dispose() {
+    elementFactory.dispose();
+  }
+
   /// Get the [LibraryElement] for the given library.
   LibraryElement getLibraryElement(Uri uri) {
     _createElementFactoryTypeProvider();
@@ -152,7 +160,7 @@
         }
       }
 
-      var resolutionKey = cycle.transitiveSignature + '.linked_bundle';
+      var resolutionKey = '${cycle.transitiveSignature}.linked_bundle';
       var resolutionBytes = byteStore.get(resolutionKey);
 
       if (resolutionBytes == null) {
@@ -206,7 +214,8 @@
         LinkResult linkResult;
         try {
           timerLinking.start();
-          linkResult = await link(elementFactory, inputLibraries);
+          linkResult = await link(elementFactory, inputLibraries,
+              macroExecutor: macroExecutor);
           librariesLinked += cycle.libraries.length;
           counterLinkedLibraries += inputLibraries.length;
           timerLinking.stop();
@@ -235,13 +244,32 @@
 
       final macroKernelBuilder = this.macroKernelBuilder;
       if (macroKernelBuilder != null && macroLibraries.isNotEmpty) {
-        var macroKernelKey = cycle.transitiveSignature + '.macro_kernel';
-        var macroKernelBytes = macroKernelBuilder.build(
-          fileSystem: _MacroFileSystem(fileSystemState),
-          libraries: macroLibraries,
-        );
-        byteStore.put(macroKernelKey, macroKernelBytes);
-        bytesPut += macroKernelBytes.length;
+        var macroKernelKey = '${cycle.transitiveSignature}.macro_kernel';
+        var macroKernelBytes = byteStore.get(macroKernelKey);
+        if (macroKernelBytes == null) {
+          macroKernelBytes = macroKernelBuilder.build(
+            fileSystem: _MacroFileSystem(fileSystemState),
+            libraries: macroLibraries,
+          );
+          byteStore.put(macroKernelKey, macroKernelBytes);
+          bytesPut += macroKernelBytes.length;
+        } else {
+          bytesGet += macroKernelBytes.length;
+        }
+
+        final macroExecutor = this.macroExecutor;
+        if (macroExecutor != null) {
+          var bundleMacroExecutor = BundleMacroExecutor(
+            macroExecutor: macroExecutor,
+            kernelBytes: macroKernelBytes,
+            libraries: cycle.libraries.map((e) => e.uri).toSet(),
+          );
+          for (var libraryFile in cycle.libraries) {
+            var libraryUriStr = libraryFile.uriStr;
+            var libraryElement = elementFactory.libraryOfUri2(libraryUriStr);
+            libraryElement.bundleMacroExecutor = bundleMacroExecutor;
+          }
+        }
       }
     }
 
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index f646b7e..f8e2426 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -40,6 +40,7 @@
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary2/ast_binary_tokens.dart';
 import 'package:analyzer/src/summary2/bundle_reader.dart';
+import 'package:analyzer/src/summary2/macro.dart';
 import 'package:analyzer/src/summary2/reference.dart';
 import 'package:analyzer/src/task/inference_error.dart';
 import 'package:collection/collection.dart';
@@ -3678,6 +3679,9 @@
   /// The scope of this library, `null` if it has not been created yet.
   LibraryScope? _scope;
 
+  /// The macro executor for the bundle to which this library belongs.
+  BundleMacroExecutor? bundleMacroExecutor;
+
   /// Initialize a newly created library element in the given [context] to have
   /// the given [name] and [offset].
   LibraryElementImpl(this.context, this.session, String name, int offset,
diff --git a/pkg/analyzer/lib/src/dart/resolver/invocation_inferrer.dart b/pkg/analyzer/lib/src/dart/resolver/invocation_inferrer.dart
index 97dad9b..fe15873 100644
--- a/pkg/analyzer/lib/src/dart/resolver/invocation_inferrer.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/invocation_inferrer.dart
@@ -18,6 +18,35 @@
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 
+Set<Object> _computeExplicitlyTypedParameterSet(
+    FunctionExpression functionExpression) {
+  List<FormalParameter> parameters =
+      functionExpression.parameters?.parameters ?? const [];
+  Set<Object> result = {};
+  for (var formalParameter in parameters) {
+    int unnamedParameterIndex = 0;
+    var key = formalParameter.isNamed
+        ? formalParameter.identifier?.name ?? ''
+        : unnamedParameterIndex++;
+    if (formalParameter.isExplicitlyTyped) {
+      result.add(key);
+    }
+  }
+  return result;
+}
+
+/// Given an iterable of parameters, computes a map whose keys are either the
+/// parameter name (for named parameters) or the zero-based integer index (for
+/// unnamed parameters), and whose values are the parameters themselves.
+Map<Object, ParameterElement> _computeParameterMap(
+    Iterable<ParameterElement> parameters) {
+  int unnamedParameterIndex = 0;
+  return {
+    for (var parameter in parameters)
+      parameter.isNamed ? parameter.name : unnamedParameterIndex++: parameter
+  };
+}
+
 /// Specialization of [InvocationInferrer] for performing type inference on AST
 /// nodes of type [Annotation] that resolve to a constructor invocation.
 class AnnotationInferrer extends FullInvocationInferrer<AnnotationImpl> {
@@ -192,15 +221,21 @@
 
     List<EqualityInfo<PromotableElement, DartType>?>? identicalInfo =
         _isIdentical ? [] : null;
+    var parameterMap = _computeParameterMap(rawType?.parameters ?? const []);
     var deferredClosures = _visitArguments(
+        parameterMap: parameterMap,
         identicalInfo: identicalInfo,
         substitution: substitution,
         inferrer: inferrer);
     if (deferredClosures != null) {
-      for (var stage in _ClosureDependencies(resolver.typeSystem,
-              deferredClosures, rawType?.typeFormals.toSet() ?? const {})
-          .planClosureReconciliationStages()) {
-        if (inferrer != null) {
+      bool isFirstStage = true;
+      for (var stage in _ClosureDependencies(
+              resolver.typeSystem,
+              deferredClosures,
+              rawType?.typeFormals.toSet() ?? const {},
+              _computeUndeferredParamInfo(parameterMap, deferredClosures))
+          .planReconciliationStages()) {
+        if (inferrer != null && !isFirstStage) {
           substitution = Substitution.fromPairs(
               rawType!.typeFormals, inferrer.partialInfer());
         }
@@ -209,6 +244,7 @@
             identicalInfo: identicalInfo,
             substitution: substitution,
             inferrer: inferrer);
+        isFirstStage = false;
       }
     }
 
@@ -234,6 +270,22 @@
     return returnType;
   }
 
+  /// Computes a list of [_ParamInfo] objects corresponding to the invocation
+  /// parameters that were *not* deferred.
+  List<_ParamInfo> _computeUndeferredParamInfo(
+      Map<Object, ParameterElement> parameterMap,
+      List<_DeferredParamInfo> deferredClosures) {
+    if (rawType == null) return const [];
+    var parameterKeysAlreadyCovered = {
+      for (var closure in deferredClosures) closure.parameterKey
+    };
+    return [
+      for (var entry in parameterMap.entries)
+        if (!parameterKeysAlreadyCovered.contains(entry.key))
+          _ParamInfo(entry.value)
+    ];
+  }
+
   DartType _refineReturnType(DartType returnType) => returnType;
 
   void _reportWrongNumberOfTypeArguments(TypeArgumentList typeArgumentList,
@@ -401,7 +453,8 @@
 
   /// Performs type inference on the invocation expression.
   void resolveInvocation() {
-    var deferredClosures = _visitArguments();
+    var deferredClosures = _visitArguments(
+        parameterMap: _computeParameterMap(rawType?.parameters ?? const []));
     if (deferredClosures != null) {
       _resolveDeferredClosures(deferredClosures: deferredClosures);
     }
@@ -426,7 +479,7 @@
 
   /// Resolves any closures that were deferred by [_visitArguments].
   void _resolveDeferredClosures(
-      {required Iterable<_DeferredClosure> deferredClosures,
+      {required Iterable<_DeferredParamInfo> deferredClosures,
       List<EqualityInfo<PromotableElement, DartType>?>? identicalInfo,
       Substitution? substitution,
       GenericInferrer? inferrer}) {
@@ -460,48 +513,34 @@
   /// Visits [argumentList], resolving each argument.  If any arguments need to
   /// be deferred due to the `inference-update-1` feature, a list of them is
   /// returned.
-  List<_DeferredClosure>? _visitArguments(
-      {List<EqualityInfo<PromotableElement, DartType>?>? identicalInfo,
+  List<_DeferredParamInfo>? _visitArguments(
+      {required Map<Object, ParameterElement> parameterMap,
+      List<EqualityInfo<PromotableElement, DartType>?>? identicalInfo,
       Substitution? substitution,
       GenericInferrer? inferrer}) {
     assert(whyNotPromotedList.isEmpty);
-    List<_DeferredClosure>? deferredClosures;
-    var parameters = rawType?.parameters;
-    var namedParameters = <String, ParameterElement>{};
-    if (parameters != null) {
-      for (var i = 0; i < parameters.length; i++) {
-        var parameter = parameters[i];
-        if (parameter.isNamed) {
-          namedParameters[parameter.name] = parameter;
-        }
-      }
-    }
+    List<_DeferredParamInfo>? deferredClosures;
     resolver.checkUnreachableNode(argumentList);
     var flow = resolver.flowAnalysis.flow;
-    var positionalParameterIndex = 0;
+    var unnamedArgumentIndex = 0;
     var arguments = argumentList.arguments;
     for (int i = 0; i < arguments.length; i++) {
       var argument = arguments[i];
       Expression value;
       ParameterElement? parameter;
+      Object parameterKey;
       if (argument is NamedExpression) {
         value = argument.expression;
-        parameter = namedParameters[argument.name.label.name];
+        parameterKey = argument.name.label.name;
       } else {
         value = argument;
-        if (parameters != null) {
-          while (positionalParameterIndex < parameters.length) {
-            var candidate = parameters[positionalParameterIndex++];
-            if (!candidate.isNamed) {
-              parameter = candidate;
-              break;
-            }
-          }
-        }
+        parameterKey = unnamedArgumentIndex++;
       }
+      parameter = parameterMap[parameterKey];
       if (resolver.isInferenceUpdate1Enabled &&
           value is FunctionExpressionImpl) {
-        (deferredClosures ??= []).add(_DeferredClosure(parameter, value, i));
+        (deferredClosures ??= [])
+            .add(_DeferredParamInfo(parameter, value, i, parameterKey));
         identicalInfo?.add(null);
         // The "why not promoted" list isn't really relevant for closures
         // because promoting a closure doesn't even make sense.  So we store an
@@ -602,24 +641,31 @@
   }
 }
 
-class _ClosureDependencies
-    extends ClosureDependencies<TypeParameterElement, _DeferredClosure> {
+class _ClosureDependencies extends ClosureDependencies<TypeParameterElement,
+    _ParamInfo, _DeferredParamInfo> {
   final TypeSystemImpl _typeSystem;
 
   final Set<TypeParameterElement> _typeVariables;
 
-  _ClosureDependencies(this._typeSystem, Iterable<_DeferredClosure> closures,
-      this._typeVariables)
-      : super(closures, _typeVariables);
+  _ClosureDependencies(
+      this._typeSystem,
+      Iterable<_DeferredParamInfo> deferredParamInfo,
+      this._typeVariables,
+      List<_ParamInfo> undeferredParamInfo)
+      : super(deferredParamInfo, _typeVariables, undeferredParamInfo);
 
   @override
-  Iterable<TypeParameterElement> typeVarsFreeInClosureArguments(
-      _DeferredClosure closure) {
-    var type = closure.parameter?.type;
+  Iterable<TypeParameterElement> typeVarsFreeInParamParams(
+      _DeferredParamInfo paramInfo) {
+    var type = paramInfo.parameter?.type;
     if (type is FunctionType) {
+      var parameterMap = _computeParameterMap(type.parameters);
+      var explicitlyTypedParameters =
+          _computeExplicitlyTypedParameterSet(paramInfo.value);
       Set<TypeParameterElement> result = {};
-      for (var parameter in type.parameters) {
-        result.addAll(_typeSystem.getFreeParameters(parameter.type,
+      for (var entry in parameterMap.entries) {
+        if (explicitlyTypedParameters.contains(entry.key)) continue;
+        result.addAll(_typeSystem.getFreeParameters(entry.value.type,
                 candidates: _typeVariables) ??
             const []);
       }
@@ -630,9 +676,9 @@
   }
 
   @override
-  Iterable<TypeParameterElement> typeVarsFreeInClosureReturns(
-      _DeferredClosure closure) {
-    var type = closure.parameter?.type;
+  Iterable<TypeParameterElement> typeVarsFreeInParamReturns(
+      _ParamInfo paramInfo) {
+    var type = paramInfo.parameter?.type;
     if (type is FunctionType) {
       return _typeSystem.getFreeParameters(type.returnType,
               candidates: _typeVariables) ??
@@ -649,15 +695,27 @@
 /// Information about an invocation argument that needs to be resolved later due
 /// to the fact that it's a closure and the `inference-update-1` feature is
 /// enabled.
-class _DeferredClosure {
-  /// The [ParameterElement] the closure is being passed to.
-  final ParameterElement? parameter;
-
+class _DeferredParamInfo extends _ParamInfo {
   /// The closure expression.
   final FunctionExpression value;
 
   /// The index into the argument list of the closure expression.
   final int index;
 
-  _DeferredClosure(this.parameter, this.value, this.index);
+  final Object parameterKey;
+
+  _DeferredParamInfo(
+      ParameterElement? parameter, this.value, this.index, this.parameterKey)
+      : super(parameter);
+}
+
+/// Information about an invocation argument that may or may not have already
+/// been resolved, as part of the deferred resolution mechanism for the
+/// `inference-update-1` feature.
+class _ParamInfo {
+  /// The function parameter corresponding to the argument, or `null` if we are
+  /// resolving a dynamic invocation.
+  final ParameterElement? parameter;
+
+  _ParamInfo(this.parameter);
 }
diff --git a/pkg/analyzer/lib/src/generated/declaration_resolver.dart b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
index c20f28d..041fc62 100644
--- a/pkg/analyzer/lib/src/generated/declaration_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
@@ -2,6 +2,9 @@
 // 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.
 
+// See: https://github.com/dart-lang/linter/issues/3345
+// ignore_for_file: prefer_initializing_formals
+
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 
diff --git a/pkg/analyzer/lib/src/summary2/library_builder.dart b/pkg/analyzer/lib/src/summary2/library_builder.dart
index 323b31e..3f1f4a4 100644
--- a/pkg/analyzer/lib/src/summary2/library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/library_builder.dart
@@ -2,18 +2,22 @@
 // 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/analysis/utilities.dart';
 import 'package:analyzer/dart/ast/ast.dart' as ast;
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/ast/ast.dart' as ast;
 import 'package:analyzer/src/dart/ast/mixin_super_invoked_names.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
+import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/summary2/combinator.dart';
 import 'package:analyzer/src/summary2/constructor_initializer_resolver.dart';
 import 'package:analyzer/src/summary2/default_value_resolver.dart';
 import 'package:analyzer/src/summary2/element_builder.dart';
 import 'package:analyzer/src/summary2/export.dart';
 import 'package:analyzer/src/summary2/link.dart';
+import 'package:analyzer/src/summary2/macro_application.dart';
 import 'package:analyzer/src/summary2/metadata_resolver.dart';
 import 'package:analyzer/src/summary2/reference.dart';
 import 'package:analyzer/src/summary2/reference_resolver.dart';
@@ -57,6 +61,10 @@
     required this.units,
   });
 
+  SourceFactory get _sourceFactory {
+    return linker.elementFactory.analysisContext.sourceFactory;
+  }
+
   void addExporters() {
     for (var element in element.exports) {
       var exportedLibrary = element.exportedLibrary;
@@ -169,6 +177,64 @@
     }
   }
 
+  Future<void> executeMacroTypesPhase() async {
+    if (!element.featureSet.isEnabled(Feature.macros)) {
+      return;
+    }
+
+    var applier = LibraryMacroApplier(this);
+    var augmentationLibrary = await applier.executeMacroTypesPhase();
+    if (augmentationLibrary == null) {
+      return;
+    }
+
+    var parseResult = parseString(
+      content: augmentationLibrary,
+      featureSet: element.featureSet,
+      throwIfDiagnostics: false,
+    );
+    var unitNode = parseResult.unit as ast.CompilationUnitImpl;
+
+    // For now we model augmentation libraries as parts.
+    var unitUri = uri.resolve('_macro_types.dart');
+    var unitElement = CompilationUnitElementImpl(
+      source: _sourceFactory.forUri2(unitUri)!,
+      librarySource: element.source,
+      lineInfo: parseResult.lineInfo,
+    )
+      ..enclosingElement = element
+      ..isSynthetic = true
+      ..uri = unitUri.toString();
+
+    var unitReference = reference.getChild('@unit').getChild('$unitUri');
+    _bindReference(unitReference, unitElement);
+
+    element.parts.add(unitElement);
+
+    ElementBuilder(
+      libraryBuilder: this,
+      unitReference: unitReference,
+      unitElement: unitElement,
+    ).buildDeclarationElements(unitNode);
+
+    units.add(
+      LinkingUnit(
+        isDefiningUnit: false,
+        reference: unitReference,
+        node: unitNode,
+        element: unitElement,
+      ),
+    );
+
+    linker.macroGeneratedUnits.add(
+      LinkMacroGeneratedUnit(
+        uri: unitUri,
+        content: parseResult.content,
+        unit: parseResult.unit,
+      ),
+    );
+  }
+
   void resolveConstructors() {
     ConstructorInitializerResolver(linker, element).resolve();
   }
@@ -281,7 +347,6 @@
       unitElements.add(unitElement);
       linkingUnits.add(
         LinkingUnit(
-          input: inputUnit,
           isDefiningUnit: isDefiningUnit,
           reference: unitReference,
           node: unitNode,
@@ -312,14 +377,12 @@
 }
 
 class LinkingUnit {
-  final LinkInputUnit input;
   final bool isDefiningUnit;
   final Reference reference;
   final ast.CompilationUnitImpl node;
   final CompilationUnitElementImpl element;
 
   LinkingUnit({
-    required this.input,
     required this.isDefiningUnit,
     required this.reference,
     required this.node,
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index d4b9866..3afe40b 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -4,6 +4,8 @@
 
 import 'dart:typed_data';
 
+import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart'
+    as macro;
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/ast/ast.dart' as ast;
 import 'package:analyzer/dart/element/element.dart';
@@ -28,12 +30,14 @@
 /// Note that AST units and tokens of [inputLibraries] will be damaged.
 Future<LinkResult> link(
   LinkedElementFactory elementFactory,
-  List<LinkInputLibrary> inputLibraries,
-) async {
-  var linker = Linker(elementFactory);
-  linker.link(inputLibraries);
+  List<LinkInputLibrary> inputLibraries, {
+  macro.MultiMacroExecutor? macroExecutor,
+}) async {
+  var linker = Linker(elementFactory, macroExecutor);
+  await linker.link(inputLibraries);
   return LinkResult(
     resolutionBytes: linker.resolutionBytes,
+    macroGeneratedUnits: linker.macroGeneratedUnits,
   );
 }
 
@@ -48,6 +52,7 @@
 
 class Linker {
   final LinkedElementFactory elementFactory;
+  final macro.MultiMacroExecutor? macroExecutor;
 
   /// Libraries that are being linked.
   final Map<Uri, LibraryBuilder> builders = {};
@@ -58,7 +63,9 @@
 
   late Uint8List resolutionBytes;
 
-  Linker(this.elementFactory);
+  final List<LinkMacroGeneratedUnit> macroGeneratedUnits = [];
+
+  Linker(this.elementFactory, this.macroExecutor);
 
   AnalysisContextImpl get analysisContext {
     return elementFactory.analysisContext;
@@ -81,12 +88,12 @@
     return elementNodes[element];
   }
 
-  void link(List<LinkInputLibrary> inputLibraries) {
+  Future<void> link(List<LinkInputLibrary> inputLibraries) async {
     for (var inputLibrary in inputLibraries) {
       LibraryBuilder.build(this, inputLibrary);
     }
 
-    _buildOutlines();
+    await _buildOutlines();
 
     timerLinkingLinkingBundle.start();
     _writeLibraries();
@@ -99,9 +106,9 @@
     }
   }
 
-  void _buildOutlines() {
+  Future<void> _buildOutlines() async {
     _createTypeSystemIfNotLinkingDartCore();
-    _computeLibraryScopes();
+    await _computeLibraryScopes();
     _createTypeSystem();
     _resolveTypes();
     _buildEnumChildren();
@@ -121,12 +128,16 @@
     }
   }
 
-  void _computeLibraryScopes() {
+  Future<void> _computeLibraryScopes() async {
     for (var library in builders.values) {
       library.buildElements();
     }
 
     for (var library in builders.values) {
+      await library.executeMacroTypesPhase();
+    }
+
+    for (var library in builders.values) {
       library.buildInitialExportScope();
     }
 
@@ -285,10 +296,24 @@
   String get uriStr => '$uri';
 }
 
+class LinkMacroGeneratedUnit {
+  final Uri uri;
+  final String content;
+  final ast.CompilationUnit unit;
+
+  LinkMacroGeneratedUnit({
+    required this.uri,
+    required this.content,
+    required this.unit,
+  });
+}
+
 class LinkResult {
   final Uint8List resolutionBytes;
+  final List<LinkMacroGeneratedUnit> macroGeneratedUnits;
 
   LinkResult({
     required this.resolutionBytes,
+    required this.macroGeneratedUnits,
   });
 }
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
index 64cb301..c296291 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -114,6 +114,12 @@
     }
   }
 
+  void dispose() {
+    for (var libraryReference in rootReference.children) {
+      _disposeLibrary(libraryReference.element);
+    }
+  }
+
   Element? elementOfReference(Reference reference) {
     if (reference.element != null) {
       return reference.element;
@@ -184,7 +190,8 @@
   void removeLibraries(Set<String> uriStrSet) {
     for (var uriStr in uriStrSet) {
       _libraryReaders.remove(uriStr);
-      rootReference.removeChild(uriStr);
+      var libraryReference = rootReference.removeChild(uriStr);
+      _disposeLibrary(libraryReference?.element);
     }
 
     analysisSession.classHierarchy.removeOfLibraries(uriStrSet);
@@ -238,4 +245,10 @@
 
     libraryElement.createLoadLibraryFunction();
   }
+
+  void _disposeLibrary(Element? libraryElement) {
+    if (libraryElement is LibraryElementImpl) {
+      libraryElement.bundleMacroExecutor?.dispose();
+    }
+  }
 }
diff --git a/pkg/analyzer/lib/src/summary2/macro.dart b/pkg/analyzer/lib/src/summary2/macro.dart
index a3502d0..74f3692 100644
--- a/pkg/analyzer/lib/src/summary2/macro.dart
+++ b/pkg/analyzer/lib/src/summary2/macro.dart
@@ -2,10 +2,72 @@
 // 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 'dart:isolate';
 import 'dart:typed_data';
 
+import 'package:_fe_analyzer_shared/src/macros/api.dart' as macro;
+import 'package:_fe_analyzer_shared/src/macros/executor.dart' as macro;
+import 'package:_fe_analyzer_shared/src/macros/executor/isolated_executor.dart'
+    as isolated_executor;
+import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart'
+    as macro;
+import 'package:_fe_analyzer_shared/src/macros/executor/serialization.dart'
+    as macro;
 import 'package:path/path.dart' as package_path;
 
+export 'package:_fe_analyzer_shared/src/macros/executor.dart' show Arguments;
+
+class BundleMacroExecutor {
+  final macro.MultiMacroExecutor macroExecutor;
+  late final macro.ExecutorFactoryToken _executorFactoryToken;
+  final Uint8List kernelBytes;
+  Uri? _kernelUriCached;
+
+  BundleMacroExecutor({
+    required this.macroExecutor,
+    required Uint8List kernelBytes,
+    required Set<Uri> libraries,
+  }) : kernelBytes = Uint8List.fromList(kernelBytes) {
+    _executorFactoryToken = macroExecutor.registerExecutorFactory(
+      () => isolated_executor.start(
+        macro.SerializationMode.byteDataServer,
+        _kernelUri,
+      ),
+      libraries,
+    );
+  }
+
+  Uri get _kernelUri {
+    return _kernelUriCached ??=
+        // ignore: avoid_dynamic_calls
+        (Isolate.current as dynamic).createUriForKernelBlob(kernelBytes);
+  }
+
+  void dispose() {
+    macroExecutor.unregisterExecutorFactory(_executorFactoryToken);
+    final kernelUriCached = _kernelUriCached;
+    if (kernelUriCached != null) {
+      // ignore: avoid_dynamic_calls
+      (Isolate.current as dynamic).unregisterKernelBlobUri(kernelUriCached);
+      _kernelUriCached = null;
+    }
+  }
+
+  Future<MacroClassInstance> instantiate({
+    required Uri libraryUri,
+    required String className,
+    required String constructorName,
+    required macro.Arguments arguments,
+    required macro.Declaration declaration,
+    required macro.IdentifierResolver identifierResolver,
+  }) async {
+    var instanceIdentifier = await macroExecutor.instantiateMacro(
+        libraryUri, className, constructorName, arguments);
+    return MacroClassInstance._(
+        this, identifierResolver, declaration, instanceIdentifier);
+  }
+}
+
 class MacroClass {
   final String name;
   final List<String> constructors;
@@ -16,6 +78,26 @@
   });
 }
 
+class MacroClassInstance {
+  final BundleMacroExecutor _bundleExecutor;
+  final macro.IdentifierResolver _identifierResolver;
+  final macro.Declaration _declaration;
+  final macro.MacroInstanceIdentifier _instanceIdentifier;
+
+  MacroClassInstance._(
+    this._bundleExecutor,
+    this._identifierResolver,
+    this._declaration,
+    this._instanceIdentifier,
+  );
+
+  Future<macro.MacroExecutionResult> executeTypesPhase() async {
+    macro.MacroExecutor executor = _bundleExecutor.macroExecutor;
+    return await executor.executeTypesPhase(
+        _instanceIdentifier, _declaration, _identifierResolver);
+  }
+}
+
 abstract class MacroFileEntry {
   String get content;
 
@@ -47,4 +129,6 @@
     required this.path,
     required this.classes,
   });
+
+  String get uriStr => uri.toString();
 }
diff --git a/pkg/analyzer/lib/src/summary2/macro_application.dart b/pkg/analyzer/lib/src/summary2/macro_application.dart
new file mode 100644
index 0000000..5ef25c0
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/macro_application.dart
@@ -0,0 +1,148 @@
+// 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' as macro;
+import 'package:_fe_analyzer_shared/src/macros/executor.dart' as macro;
+import 'package:_fe_analyzer_shared/src/macros/executor/introspection_impls.dart'
+    as macro;
+import 'package:_fe_analyzer_shared/src/macros/executor/remote_instance.dart'
+    as macro;
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/summary2/library_builder.dart';
+import 'package:analyzer/src/summary2/macro.dart';
+
+class LibraryMacroApplier {
+  final LibraryBuilder libraryBuilder;
+
+  final Map<ClassDeclaration, macro.ClassDeclaration> _classDeclarations = {};
+
+  LibraryMacroApplier(this.libraryBuilder);
+
+  /// TODO(scheglov) check `shouldExecute`.
+  /// TODO(scheglov) check `supportsDeclarationKind`.
+  Future<String?> executeMacroTypesPhase() async {
+    var macroResults = <macro.MacroExecutionResult>[];
+    for (var unitElement in libraryBuilder.element.units) {
+      for (var classElement in unitElement.classes) {
+        var classNode = libraryBuilder.linker.elementNodes[classElement];
+        // TODO(scheglov) support other declarations
+        if (classNode is ClassDeclaration) {
+          for (var annotation in classNode.metadata) {
+            var annotationNameNode = annotation.name;
+            if (annotationNameNode is SimpleIdentifier &&
+                annotation.arguments != null) {
+              // TODO(scheglov) Create a Scope.
+              for (var import in libraryBuilder.element.imports) {
+                var importedLibrary = import.importedLibrary;
+                if (importedLibrary is LibraryElementImpl) {
+                  var importedUri = importedLibrary.source.uri;
+                  if (!libraryBuilder.linker.builders
+                      .containsKey(importedUri)) {
+                    var lookupResult = importedLibrary.scope.lookup(
+                      annotationNameNode.name,
+                    );
+                    var getter = lookupResult.getter;
+                    if (getter is ClassElementImpl && getter.isMacro) {
+                      var macroExecutor = importedLibrary.bundleMacroExecutor;
+                      if (macroExecutor != null) {
+                        var macroResult = await _runSingleMacro(
+                          macroExecutor,
+                          getClassDeclaration(classNode),
+                          getter,
+                        );
+                        if (macroResult.isNotEmpty) {
+                          macroResults.add(macroResult);
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+
+    var macroExecutor = libraryBuilder.linker.macroExecutor;
+    if (macroExecutor != null && macroResults.isNotEmpty) {
+      var code = macroExecutor.buildAugmentationLibrary(
+        macroResults,
+        _resolveIdentifier,
+        _inferOmittedType,
+      );
+      return code.trim();
+    }
+    return null;
+  }
+
+  macro.ClassDeclaration getClassDeclaration(ClassDeclaration node) {
+    return _classDeclarations[node] ??= _createClassDeclaration(node);
+  }
+
+  macro.ClassDeclaration _createClassDeclaration(ClassDeclaration node) {
+    return macro.ClassDeclarationImpl(
+      id: macro.RemoteInstance.uniqueId,
+      identifier: _IdentifierImpl(
+        id: macro.RemoteInstance.uniqueId,
+        name: node.name.name,
+      ),
+      // TODO(scheglov): Support typeParameters
+      typeParameters: [],
+      // TODO(scheglov): Support interfaces
+      interfaces: [],
+      isAbstract: node.abstractKeyword != null,
+      isExternal: false,
+      // TODO(scheglov): Support mixins
+      mixins: [],
+      // TODO(scheglov): Support superclass
+      superclass: null,
+    );
+  }
+
+  macro.TypeAnnotation _inferOmittedType(
+    macro.OmittedTypeAnnotation omittedType,
+  ) {
+    throw UnimplementedError();
+  }
+
+  macro.ResolvedIdentifier _resolveIdentifier(macro.Identifier identifier) {
+    throw UnimplementedError();
+  }
+
+  Future<macro.MacroExecutionResult> _runSingleMacro(
+    BundleMacroExecutor macroExecutor,
+    macro.Declaration declaration,
+    ClassElementImpl classElement,
+  ) async {
+    var macroInstance = await macroExecutor.instantiate(
+      libraryUri: classElement.librarySource.uri,
+      className: classElement.name,
+      constructorName: '', // TODO
+      arguments: Arguments([], {}), // TODO
+      declaration: declaration,
+      identifierResolver: _FakeIdentifierResolver(),
+    );
+    return await macroInstance.executeTypesPhase();
+  }
+}
+
+class _FakeIdentifierResolver extends macro.IdentifierResolver {
+  @override
+  Future<macro.Identifier> resolveIdentifier(Uri library, String name) {
+    // TODO: implement resolveIdentifier
+    throw UnimplementedError();
+  }
+}
+
+class _IdentifierImpl extends macro.IdentifierImpl {
+  _IdentifierImpl({required int id, required String name})
+      : super(id: id, name: name);
+}
+
+extension on macro.MacroExecutionResult {
+  bool get isNotEmpty =>
+      libraryAugmentations.isNotEmpty || classAugmentations.isNotEmpty;
+}
diff --git a/pkg/analyzer/lib/src/util/lru_map.dart b/pkg/analyzer/lib/src/util/lru_map.dart
index 66f6129..fe2cb1e 100644
--- a/pkg/analyzer/lib/src/util/lru_map.dart
+++ b/pkg/analyzer/lib/src/util/lru_map.dart
@@ -37,7 +37,7 @@
     _map[key] = value;
     if (_map.length > _maxSize) {
       K evictedKey = _map.keys.first;
-      V evictedValue = _map.remove(evictedKey)!;
+      V evictedValue = _map.remove(evictedKey) as V;
       if (_handler != null) {
         _handler!.call(evictedKey, evictedValue);
       }
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index ae91994..e0b366d 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -29,6 +29,7 @@
   kernel:
     path: ../kernel
   linter: ^1.12.0
+  lints: ^2.0.0
   matcher: ^0.12.10
   test: ^1.16.0
   test_reflective_loader: ^0.2.0
diff --git a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
index 5b9d9a4..85b0d8c 100644
--- a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
@@ -177,7 +177,9 @@
   }
 
   void disposeAnalysisContextCollection() {
-    if (_analysisContextCollection != null) {
+    final analysisContextCollection = _analysisContextCollection;
+    if (analysisContextCollection != null) {
+      analysisContextCollection.dispose();
       _analysisContextCollection = null;
     }
   }
@@ -216,6 +218,10 @@
     );
   }
 
+  Future<void> tearDown() async {
+    disposeAnalysisContextCollection();
+  }
+
   /// Override this method to update [analysisOptions] for every context root,
   /// the default or already updated with `analysis_options.yaml` file.
   void updateAnalysisOptions(AnalysisOptionsImpl analysisOptions) {}
diff --git a/pkg/analyzer/test/src/dart/resolution/macro_test.dart b/pkg/analyzer/test/src/dart/resolution/macro_test.dart
index 2b41573..a3d12b2 100644
--- a/pkg/analyzer/test/src/dart/resolution/macro_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/macro_test.dart
@@ -34,6 +34,9 @@
   void setUp() {
     super.setUp();
 
+    // TODO(scheglov) Dependency tracking for macros is not right yet.
+    useEmptyByteStore();
+
     writeTestPackageConfig(
       PackageConfigFileBuilder(),
       macrosEnvironment: MacrosEnvironment.instance,
@@ -41,14 +44,30 @@
   }
 
   test_0() async {
-    await assertNoErrorsInCode(r'''
+    newFile2('$testPackageLibPath/a.dart', r'''
 import 'dart:async';
 import 'package:_fe_analyzer_shared/src/macros/api.dart';
 
 macro class EmptyMacro implements ClassTypesMacro {
   const EmptyMacro();
-  FutureOr<void> buildTypesForClass(clazz, builder) {}
+
+  FutureOr<void> buildTypesForClass(clazz, builder) {
+    var targetName = clazz.identifier.name;
+    builder.declareType(
+      '${targetName}_Macro',
+      DeclarationCode.fromString('class ${targetName}_Macro {}'),
+    );
+  }
 }
 ''');
+
+    await assertNoErrorsInCode('''
+import 'a.dart';
+
+@EmptyMacro()
+class A {}
+
+void f(A_Macro a) {}
+''');
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/inference_update_1_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/inference_update_1_test.dart
index f6700c42..81d22f9 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/inference_update_1_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/inference_update_1_test.dart
@@ -205,6 +205,66 @@
         _isEnabled ? 'int' : 'Object?');
   }
 
+  test_horizontal_inference_unnecessary_due_to_explicit_parameter_type() async {
+    // In this example, there is no need for horizontal type inference because
+    // the type of `x` is explicit.
+    await assertErrorsInCode('''
+test(List<int> list) {
+  var a = list.fold(null, (int? x, y) => (x ?? 0) + y);
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 29, 1),
+    ]);
+    assertType(findElement.localVar('a').type, 'int?');
+    assertType(findElement.parameter('x').type, 'int?');
+    assertType(findElement.parameter('y').type, 'int');
+    expect(findNode.binary('+ y').staticElement!.enclosingElement.name, 'num');
+  }
+
+  test_horizontal_inference_unnecessary_due_to_explicit_parameter_type_named() async {
+    // In this example, there is no need for horizontal type inference because
+    // the type of `x` is explicit.
+    await assertErrorsInCode('''
+T f<T>(T a, T Function({required T x, required int y}) b) => throw '';
+test() {
+  var a = f(null, ({int? x, required y}) => (x ?? 0) + y);
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 86, 1),
+    ]);
+    assertType(findElement.localVar('a').type, 'int?');
+    assertType(findElement.parameter('x').type, 'int?');
+    assertType(findElement.parameter('y').type, 'int');
+    expect(findNode.binary('+ y').staticElement!.enclosingElement.name, 'num');
+  }
+
+  test_horizontal_inference_unnecessary_due_to_no_dependency() async {
+    // In this example, there is no dependency between the two parameters of
+    // `f`, so there should be no horizontal type inference between inferring
+    // `null` and inferring `() => 0`.  (If there were horizontal type inference
+    // between them, that would be a problem, because we would infer a type of
+    // `null` for `T`).
+    await assertNoErrorsInCode('''
+void f<T>(T Function() g, T t) {}
+test() => f(() => 0, null);
+''');
+    assertType(
+        findNode.methodInvocation('f(').typeArgumentTypes!.single, 'int?');
+    assertType(findNode.methodInvocation('f(').staticInvokeType,
+        'void Function(int? Function(), int?)');
+  }
+
+  test_horizontal_inference_with_callback() async {
+    await assertNoErrorsInCode('''
+test(void Function<T>(T, void Function(T)) f) {
+  f(0, (x) {
+    x;
+  });
+}
+''');
+    assertType(findNode.simple('x;'), _isEnabled ? 'int' : 'Object?');
+  }
+
   test_write_capture_deferred() async {
     await assertNoErrorsInCode('''
 test(int? i) {
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/instance_creation_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/instance_creation_test.dart
index 9289e3a..28a3686 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/instance_creation_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/instance_creation_test.dart
@@ -27,7 +27,7 @@
     return <TestDescriptor>[
       TestDescriptor(
           '${keyword}_keyword',
-          '$keyword',
+          keyword,
           [
             ParserErrorCode.MISSING_IDENTIFIER,
             ParserErrorCode.EXPECTED_TOKEN,
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index d8bae60..5790c59 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -919,7 +919,7 @@
       if (uri.isScheme('file')) {
         uriStr = uri.pathSegments.last;
       }
-      buffer.write('$uriStr');
+      buffer.write(uriStr);
     } else {
       buffer.write('<unresolved>');
     }
diff --git a/pkg/analyzer/test/src/summary/elements_base.dart b/pkg/analyzer/test/src/summary/elements_base.dart
index f3d2095..d0e24164 100644
--- a/pkg/analyzer/test/src/summary/elements_base.dart
+++ b/pkg/analyzer/test/src/summary/elements_base.dart
@@ -4,12 +4,15 @@
 
 import 'dart:typed_data';
 
+import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart'
+    as macro;
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/context.dart';
 import 'package:analyzer/src/dart/analysis/session.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/class_hierarchy.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
@@ -22,10 +25,12 @@
 import 'package:analyzer/src/summary2/informative_data.dart';
 import 'package:analyzer/src/summary2/link.dart';
 import 'package:analyzer/src/summary2/linked_element_factory.dart';
+import 'package:analyzer/src/summary2/macro.dart';
 import 'package:analyzer/src/summary2/reference.dart';
 import 'package:analyzer/src/test_utilities/mock_sdk.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:analyzer/src/util/uri.dart';
+import 'package:path/path.dart' as package_path;
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../../util/feature_sets.dart';
@@ -37,6 +42,9 @@
   /// The shared SDK bundle, computed once and shared among test invocations.
   static _SdkBundle? _sdkBundle;
 
+  MacroKernelBuilder? macroKernelBuilder;
+  macro.MultiMacroExecutor? macroExecutor;
+
   /// The set of features enabled in this test.
   FeatureSet featureSet = FeatureSets.latestWithExperiments;
 
@@ -113,7 +121,9 @@
 
   String get testPackageLibPath => '$testPackageRootPath/lib';
 
-  String get testPackageRootPath => '/home/test';
+  String get testPackageRootPath => '$workspaceRootPath/test';
+
+  String get workspaceRootPath => '/home';
 
   void addSource(String path, String contents) {
     newFile2(path, contents);
@@ -123,6 +133,7 @@
     String text, {
     bool allowErrors = false,
     bool dumpSummaries = false,
+    List<Set<String>>? preBuildSequence,
   }) async {
     var testFile = newFile2(testFilePath, text);
     var testUri = sourceFactory.pathToUri(testFile.path)!;
@@ -160,7 +171,22 @@
       ),
     );
 
-    var linkResult = await link(elementFactory, inputLibraries);
+    _linkConfiguredLibraries(
+      elementFactory,
+      inputLibraries,
+      preBuildSequence,
+    );
+
+    var linkResult = await link(
+      elementFactory,
+      inputLibraries,
+      macroExecutor: macroExecutor,
+    );
+
+    for (var macroUnit in linkResult.macroGeneratedUnits) {
+      var informativeBytes = writeUnitInformative(macroUnit.unit);
+      unitsInformativeBytes[macroUnit.uri] = informativeBytes;
+    }
 
     if (!keepLinkingLibraries) {
       elementFactory.removeBundle(
@@ -279,6 +305,79 @@
     }
   }
 
+  /// If there are any [macroLibraries], build the kernel and prepare for
+  /// execution.
+  void _buildMacroLibraries(
+    LinkedElementFactory elementFactory,
+    List<MacroLibrary> macroLibraries,
+  ) {
+    if (macroLibraries.isEmpty) {
+      return;
+    }
+
+    final macroKernelBuilder = this.macroKernelBuilder;
+    if (macroKernelBuilder == null) {
+      return;
+    }
+
+    final macroExecutor = this.macroExecutor;
+    if (macroExecutor == null) {
+      return;
+    }
+
+    var macroKernelBytes = macroKernelBuilder.build(
+      fileSystem: _MacroFileSystem(resourceProvider),
+      libraries: macroLibraries,
+    );
+
+    var bundleMacroExecutor = BundleMacroExecutor(
+      macroExecutor: macroExecutor,
+      kernelBytes: macroKernelBytes,
+      libraries: macroLibraries.map((e) => e.uri).toSet(),
+    );
+
+    for (var macroLibrary in macroLibraries) {
+      var uriStr = macroLibrary.uriStr;
+      var element = elementFactory.libraryOfUri2(uriStr);
+      element.bundleMacroExecutor = bundleMacroExecutor;
+    }
+  }
+
+  /// If there are any libraries in the [uriStrSetList], link these subsets
+  /// of [inputLibraries] (and remove from it), build macro kernels, prepare
+  /// for executing macros.
+  void _linkConfiguredLibraries(
+    LinkedElementFactory elementFactory,
+    List<LinkInputLibrary> inputLibraries,
+    List<Set<String>>? uriStrSetList,
+  ) {
+    if (uriStrSetList == null) {
+      return;
+    }
+
+    for (var uriStrSet in uriStrSetList) {
+      var cycleInputLibraries = <LinkInputLibrary>[];
+      var macroLibraries = <MacroLibrary>[];
+      for (var inputLibrary in inputLibraries) {
+        if (uriStrSet.contains(inputLibrary.uriStr)) {
+          cycleInputLibraries.add(inputLibrary);
+          _addMacroLibrary(macroLibraries, inputLibrary);
+        }
+      }
+
+      link(
+        elementFactory,
+        cycleInputLibraries,
+        macroExecutor: macroExecutor,
+      );
+
+      _buildMacroLibraries(elementFactory, macroLibraries);
+
+      // Remove libraries that we just linked.
+      cycleInputLibraries.forEach(inputLibraries.remove);
+    }
+  }
+
   String _readSafely(String path) {
     try {
       var file = resourceProvider.getFile(path);
@@ -287,6 +386,53 @@
       return '';
     }
   }
+
+  /// If there are any macros in the [inputLibrary], add it.
+  static void _addMacroLibrary(
+    List<MacroLibrary> macroLibraries,
+    LinkInputLibrary inputLibrary,
+  ) {
+    var macroClasses = <MacroClass>[];
+    for (var inputUnit in inputLibrary.units) {
+      for (var declaration in inputUnit.unit.declarations) {
+        if (declaration is ClassDeclarationImpl &&
+            declaration.macroKeyword != null) {
+          var constructors =
+              declaration.members.whereType<ConstructorDeclaration>().toList();
+          if (constructors.isEmpty) {
+            macroClasses.add(
+              MacroClass(
+                name: declaration.name.name,
+                constructors: [''],
+              ),
+            );
+          } else {
+            var constructorNames = constructors
+                .map((e) => e.name?.name ?? '')
+                .where((e) => !e.startsWith('_'))
+                .toList();
+            if (constructorNames.isNotEmpty) {
+              macroClasses.add(
+                MacroClass(
+                  name: declaration.name.name,
+                  constructors: constructorNames,
+                ),
+              );
+            }
+          }
+        }
+      }
+    }
+    if (macroClasses.isNotEmpty) {
+      macroLibraries.add(
+        MacroLibrary(
+          uri: inputLibrary.uri,
+          path: inputLibrary.source.fullName,
+          classes: macroClasses,
+        ),
+      );
+    }
+  }
 }
 
 class _AnalysisSessionForLinking implements AnalysisSessionImpl {
@@ -300,6 +446,35 @@
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
 
+/// [MacroFileEntry] adapter for [File].
+class _MacroFileEntry implements MacroFileEntry {
+  final File file;
+
+  _MacroFileEntry(this.file);
+
+  @override
+  String get content => file.readAsStringSync();
+
+  @override
+  bool get exists => file.exists;
+}
+
+/// [MacroFileSystem] adapter for [ResourceProvider].
+class _MacroFileSystem implements MacroFileSystem {
+  final ResourceProvider resourceProvider;
+
+  _MacroFileSystem(this.resourceProvider);
+
+  @override
+  package_path.Context get pathContext => resourceProvider.pathContext;
+
+  @override
+  MacroFileEntry getFile(String path) {
+    var file = resourceProvider.getFile(path);
+    return _MacroFileEntry(file);
+  }
+}
+
 class _SdkBundle {
   final Uint8List resolutionBytes;
 
diff --git a/pkg/analyzer/test/src/summary/macro_test.dart b/pkg/analyzer/test/src/summary/macro_test.dart
index be36b5a..c46dce0 100644
--- a/pkg/analyzer/test/src/summary/macro_test.dart
+++ b/pkg/analyzer/test/src/summary/macro_test.dart
@@ -2,12 +2,25 @@
 // 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/multi_executor.dart'
+    as macro;
+import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
+import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'element_text.dart';
 import 'elements_base.dart';
+import 'repository_macro_kernel_builder.dart';
 
 main() {
+  try {
+    MacrosEnvironment.instance;
+  } catch (_) {
+    print('Cannot initialize environment. Skip macros tests.');
+    test('fake', () {});
+    return;
+  }
+
   defineReflectiveSuite(() {
     defineReflectiveTests(MacroElementsKeepLinkingTest);
     defineReflectiveTests(MacroElementsFromBytesTest);
@@ -30,6 +43,79 @@
   @override
   bool get keepLinkingLibraries => false;
 
+  /// The path for external packages.
+  String get packagesRootPath => '/packages';
+
+  Future<void> setUp() async {
+    writeTestPackageConfig(
+      PackageConfigFileBuilder(),
+      macrosEnvironment: MacrosEnvironment.instance,
+    );
+
+    macroKernelBuilder = DartRepositoryMacroKernelBuilder(
+      MacrosEnvironment.instance.platformDillBytes,
+    );
+
+    macroExecutor = macro.MultiMacroExecutor();
+  }
+
+  Future<void> tearDown() async {
+    await macroExecutor?.close();
+  }
+
+  test_build_types() async {
+    newFile2('$testPackageLibPath/a.dart', r'''
+import 'dart:async';
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+
+macro class MyMacro implements ClassTypesMacro {
+  FutureOr<void> buildTypesForClass(clazz, builder) {
+    builder.declareType(
+      'MyClass',
+      DeclarationCode.fromString('class MyClass {}'),
+    );
+  }
+}
+''');
+
+    var library = await buildLibrary(r'''
+import 'a.dart';
+
+@MyMacro()
+class A {}
+''', preBuildSequence: [
+      {'package:test/a.dart'}
+    ]);
+
+    checkElementText(library, r'''
+library
+  imports
+    package:test/a.dart
+  definingUnit
+    classes
+      class A @35
+        metadata
+          Annotation
+            atSign: @ @18
+            name: SimpleIdentifier
+              token: MyMacro @19
+              staticElement: package:test/a.dart::@class::MyMacro
+              staticType: null
+            arguments: ArgumentList
+              leftParenthesis: ( @26
+              rightParenthesis: ) @27
+            element: package:test/a.dart::@class::MyMacro::@constructor::•
+        constructors
+          synthetic @-1
+  parts
+    package:test/_macro_types.dart
+      classes
+        class MyClass @6
+          constructors
+            synthetic @-1
+''');
+  }
+
   test_class_macro() async {
     var library = await buildLibrary(r'''
 macro class A {}
@@ -72,4 +158,32 @@
           Object
 ''');
   }
+
+  void writeTestPackageConfig(
+    PackageConfigFileBuilder config, {
+    MacrosEnvironment? macrosEnvironment,
+  }) {
+    config = config.copy();
+
+    config.add(
+      name: 'test',
+      rootPath: testPackageRootPath,
+    );
+
+    if (macrosEnvironment != null) {
+      var packagesRootFolder = getFolder(packagesRootPath);
+      macrosEnvironment.packageSharedFolder.copyTo(packagesRootFolder);
+      config.add(
+        name: '_fe_analyzer_shared',
+        rootPath: getFolder('$packagesRootPath/_fe_analyzer_shared').path,
+      );
+    }
+
+    newPackageConfigJsonFile(
+      testPackageRootPath,
+      config.toContent(
+        toUriStr: toUriStr,
+      ),
+    );
+  }
 }
diff --git a/pkg/analyzer/test/src/summary/repository_macro_kernel_builder.dart b/pkg/analyzer/test/src/summary/repository_macro_kernel_builder.dart
index 615a927..8af654a 100644
--- a/pkg/analyzer/test/src/summary/repository_macro_kernel_builder.dart
+++ b/pkg/analyzer/test/src/summary/repository_macro_kernel_builder.dart
@@ -92,7 +92,7 @@
 /// Just like [DartRepositoryMacroKernelBuilder], this is a temporary
 /// implementation.
 class MacrosEnvironment {
-  static late final instance = MacrosEnvironment._();
+  static final instance = MacrosEnvironment._();
 
   final _resourceProvider = MemoryResourceProvider(context: package_path.posix);
   late final Uint8List platformDillBytes;
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index db57448..afb2f16 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -2890,9 +2890,9 @@
 class L<T> {}
 class M<T> extends L<T> {}
 //     L<dynamic|Object>
-//    /              \
+//    /              
 // M<dynamic|Object>  L<A>
-//    \              /
+//                  /
 //          M<A>
 // In normal Dart, there are additional edges
 //  from M<A> to M<dynamic>
diff --git a/pkg/analyzer/test/src/util/glob_test.dart b/pkg/analyzer/test/src/util/glob_test.dart
index 30ba6c7..3810b76 100644
--- a/pkg/analyzer/test/src/util/glob_test.dart
+++ b/pkg/analyzer/test/src/util/glob_test.dart
@@ -33,7 +33,7 @@
   void test_specialChars() {
     Glob glob = Glob(r'/', r'*.dart');
     expect(glob.matches(r'a.dart'), isTrue);
-    expect(glob.matches('_-\a.dart'), isTrue);
+    expect(glob.matches('_-a.dart'), isTrue);
     expect(glob.matches(r'^$*?.dart'), isTrue);
     expect(glob.matches(r'()[]{}.dart'), isTrue);
     expect(glob.matches('\u2665.dart'), isTrue);
@@ -99,7 +99,7 @@
   void test_specialChars() {
     Glob glob = Glob(r'\', r'*.dart');
     expect(glob.matches(r'a.dart'), isTrue);
-    expect(glob.matches('_-\a.dart'), isTrue);
+    expect(glob.matches('_-a.dart'), isTrue);
     expect(glob.matches(r'^$*?.dart'), isTrue);
     expect(glob.matches(r'()[]{}.dart'), isTrue);
     expect(glob.matches('\u2665.dart'), isTrue);
diff --git a/pkg/analyzer/test/src/workspace/bazel_watcher_test.dart b/pkg/analyzer/test/src/workspace/bazel_watcher_test.dart
index 23817f4..e33dd39 100644
--- a/pkg/analyzer/test/src/workspace/bazel_watcher_test.dart
+++ b/pkg/analyzer/test/src/workspace/bazel_watcher_test.dart
@@ -159,7 +159,7 @@
     ];
     _MockPollTrigger? trigger1;
     _MockPollTrigger? trigger2;
-    var triggerFactory = (String workspace) {
+    _MockPollTrigger triggerFactory(String workspace) {
       if (workspace == convertPath('/workspace1')) {
         trigger1 = _MockPollTrigger();
         return trigger1!;
@@ -169,7 +169,8 @@
       } else {
         throw ArgumentError('Got unexpected workspace: `$workspace`');
       }
-    };
+    }
+
     var recPort = ReceivePort();
     // Note that we provide below a dummy `ReceivePort` that will *not* be used.
     // We'll directly call `handleRequest` to avoid any problems with various
@@ -240,8 +241,8 @@
 
     // The `_addResources`/`_deleteResources` functions recognize a folder by a
     // trailing `/`, but everywhere else we need to use normalized paths.
-    var addFolder = (path) => _addResources(['$path/']);
-    var deleteFolder = (path) => _deleteResources(['$path/']);
+    void addFolder(path) => _addResources(['$path/']);
+    void deleteFolder(path) => _deleteResources(['$path/']);
 
     var candidates = [
       convertPath('/workspace/bazel-out'),
diff --git a/pkg/analyzer/tool/analysis_driver/inspect_exception.dart b/pkg/analyzer/tool/analysis_driver/inspect_exception.dart
index 4eda86e..e0d467c 100644
--- a/pkg/analyzer/tool/analysis_driver/inspect_exception.dart
+++ b/pkg/analyzer/tool/analysis_driver/inspect_exception.dart
@@ -38,9 +38,9 @@
 
   for (var file in context.files) {
     print("=" * 40);
-    print('${file.path}');
+    print(file.path);
     print("-" * 40);
-    print('${file.content}');
+    print(file.content);
     print('');
     print('');
     print('');
diff --git a/pkg/analyzer/tool/messages/error_code_info.dart b/pkg/analyzer/tool/messages/error_code_info.dart
index d64f3b7..0b1d48e 100644
--- a/pkg/analyzer/tool/messages/error_code_info.dart
+++ b/pkg/analyzer/tool/messages/error_code_info.dart
@@ -99,7 +99,7 @@
 /// strings.  TODO(paulberry): share this regexp (and the code for interpreting
 /// it) between the CFE and analyzer.
 final RegExp _placeholderPattern =
-    RegExp("#\([-a-zA-Z0-9_]+\)(?:%\([0-9]*\)\.\([0-9]+\))?");
+    RegExp("#([-a-zA-Z0-9_]+)(?:%([0-9]*).([0-9]+))?");
 
 /// Convert a CFE template string (which uses placeholders like `#string`) to
 /// an analyzer template string (which uses placeholders like `{0}`).
diff --git a/pkg/analyzer/tool/summary/mini_ast.dart b/pkg/analyzer/tool/summary/mini_ast.dart
index ec11a1e..20c7dd4 100644
--- a/pkg/analyzer/tool/summary/mini_ast.dart
+++ b/pkg/analyzer/tool/summary/mini_ast.dart
@@ -361,8 +361,7 @@
     var constructorName = popIfNotNull(periodBeforeName) as String?;
     pop(); // Type arguments
     var name = pop() as String;
-    push(Annotation(name, constructorName,
-        arguments == null ? null : arguments.cast<Expression>()));
+    push(Annotation(name, constructorName, arguments?.cast<Expression>()));
   }
 
   @override
diff --git a/runtime/tests/vm/dart/finalizer/finalizer_zone_run_gc_test.dart b/runtime/tests/vm/dart/finalizer/finalizer_zone_run_gc_test.dart
index bcc6d9e1..3c5dfa1 100644
--- a/runtime/tests/vm/dart/finalizer/finalizer_zone_run_gc_test.dart
+++ b/runtime/tests/vm/dart/finalizer/finalizer_zone_run_gc_test.dart
@@ -45,6 +45,9 @@
 
   // Now we have.
   Expect.equals(expectedZone, actualZone);
+
+  // Make sure finalizer is still reachable.
+  reachabilityFence(finalizer);
 }
 
 Future<void> testFinalizerException() async {
@@ -70,4 +73,7 @@
   Expect.isNull(caughtError);
   await yieldToMessageLoop();
   Expect.isNotNull(caughtError);
+
+  // Make sure finalizer is still reachable.
+  reachabilityFence(finalizer);
 }
diff --git a/runtime/tests/vm/dart/finalizer/helpers.dart b/runtime/tests/vm/dart/finalizer/helpers.dart
index d776098..3fdb3de 100644
--- a/runtime/tests/vm/dart/finalizer/helpers.dart
+++ b/runtime/tests/vm/dart/finalizer/helpers.dart
@@ -53,3 +53,10 @@
   _namedPrint(name)('Await done.');
   return null;
 }
+
+// Uses [object] to guarantee it is reachable.
+@pragma('vm:never-inline')
+void reachabilityFence(Object? object) {
+  // Make sure [object] parameter is used and not tree shaken.
+  object.toString();
+}
diff --git a/runtime/tests/vm/dart_2/finalizer/finalizer_zone_run_gc_test.dart b/runtime/tests/vm/dart_2/finalizer/finalizer_zone_run_gc_test.dart
index 17646d1..d5b0f66 100644
--- a/runtime/tests/vm/dart_2/finalizer/finalizer_zone_run_gc_test.dart
+++ b/runtime/tests/vm/dart_2/finalizer/finalizer_zone_run_gc_test.dart
@@ -47,6 +47,9 @@
 
   // Now we have.
   Expect.equals(expectedZone, actualZone);
+
+  // Make sure finalizer is still reachable.
+  reachabilityFence(finalizer);
 }
 
 Future<void> testFinalizerException() async {
@@ -72,4 +75,7 @@
   Expect.isNull(caughtError);
   await yieldToMessageLoop();
   Expect.isNotNull(caughtError);
+
+  // Make sure finalizer is still reachable.
+  reachabilityFence(finalizer);
 }
diff --git a/runtime/tests/vm/dart_2/finalizer/helpers.dart b/runtime/tests/vm/dart_2/finalizer/helpers.dart
index a82646c..653f8e5 100644
--- a/runtime/tests/vm/dart_2/finalizer/helpers.dart
+++ b/runtime/tests/vm/dart_2/finalizer/helpers.dart
@@ -55,3 +55,10 @@
   _namedPrint(name)('Await done.');
   return null;
 }
+
+// Uses [object] to guarantee it is reachable.
+@pragma('vm:never-inline')
+void reachabilityFence(Object object) {
+  // Make sure [object] parameter is used and not tree shaken.
+  object.toString();
+}
diff --git a/tests/language/inference_update_1/horizontal_inference_disabled_test.dart b/tests/language/inference_update_1/horizontal_inference_disabled_test.dart
index e335aee..c63166b 100644
--- a/tests/language/inference_update_1/horizontal_inference_disabled_test.dart
+++ b/tests/language/inference_update_1/horizontal_inference_disabled_test.dart
@@ -44,4 +44,19 @@
   f(0, (x) => [x]).expectStaticType<Exactly<List<Object?>>>();
 }
 
+testUnnecessaryDueToNoDependency(T Function<T>(T Function(), T) f) {
+  f(() => 0, null).expectStaticType<Exactly<int?>>();
+}
+
+testUnnecessaryDueToExplicitParameterType(List<int> list) {
+  var a = list.fold(null, (int? x, y) => (x ?? 0) + y);
+  a.expectStaticType<Exactly<int?>>();
+}
+
+testUnnecessaryDueToExplicitParameterTypeNamed(
+    T Function<T>(T, T Function({required T x, required int y})) f) {
+  var a = f(null, ({int? x, required y}) => (x ?? 0) + y);
+  a.expectStaticType<Exactly<int?>>();
+}
+
 main() {}
diff --git a/tests/language/inference_update_1/horizontal_inference_enabled_test.dart b/tests/language/inference_update_1/horizontal_inference_enabled_test.dart
index 33b32df..6191c06 100644
--- a/tests/language/inference_update_1/horizontal_inference_enabled_test.dart
+++ b/tests/language/inference_update_1/horizontal_inference_enabled_test.dart
@@ -107,4 +107,19 @@
   });
 }
 
+testUnnecessaryDueToNoDependency(T Function<T>(T Function(), T) f) {
+  f(() => 0, null).expectStaticType<Exactly<int?>>();
+}
+
+testUnnecessaryDueToExplicitParameterType(List<int> list) {
+  var a = list.fold(null, (int? x, y) => (x ?? 0) + y);
+  a.expectStaticType<Exactly<int?>>();
+}
+
+testUnnecessaryDueToExplicitParameterTypeNamed(
+    T Function<T>(T, T Function({required T x, required int y})) f) {
+  var a = f(null, ({int? x, required y}) => (x ?? 0) + y);
+  a.expectStaticType<Exactly<int?>>();
+}
+
 main() {}
diff --git a/tools/VERSION b/tools/VERSION
index 88dbd87..84d1f8d 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 18
 PATCH 0
-PRERELEASE 11
+PRERELEASE 12
 PRERELEASE_PATCH 0
\ No newline at end of file