Version 2.18.0-103.0.dev

Merge commit '063ee76dc7bdf43bf25f3f1fbb2885c48f3037ae' into 'dev'
diff --git a/DEPS b/DEPS
index b6d3a6b..2075bbb 100644
--- a/DEPS
+++ b/DEPS
@@ -54,7 +54,7 @@
 
   # Checkout Android dependencies only on Mac and Linux.
   "download_android_deps":
-    "(host_os == mac or host_os == linux) and host_cpu == x64",
+    "host_os == mac or (host_os == linux and host_cpu == x64)",
 
   # Checkout extra javascript engines for testing or benchmarking.
   # d8, the V8 shell, is always checked out.
@@ -528,7 +528,7 @@
   Var("dart_root") + "/third_party/android_tools/ndk": {
       "packages": [
           {
-            "package": "flutter/android/ndk/${{platform}}",
+            "package": "flutter/android/ndk/${{os}}-amd64",
             "version": "version:r21.0.6113669"
           }
       ],
@@ -539,7 +539,7 @@
   Var("dart_root") + "/third_party/android_tools/sdk/build-tools": {
       "packages": [
           {
-            "package": "flutter/android/sdk/build-tools/${{platform}}",
+            "package": "flutter/android/sdk/build-tools/${{os}}-amd64",
             "version": "version:30.0.1"
           }
       ],
@@ -550,7 +550,7 @@
   Var("dart_root") + "/third_party/android_tools/sdk/platform-tools": {
      "packages": [
           {
-            "package": "flutter/android/sdk/platform-tools/${{platform}}",
+            "package": "flutter/android/sdk/platform-tools/${{os}}-amd64",
             "version": "version:29.0.2"
           }
       ],
@@ -572,7 +572,7 @@
   Var("dart_root") + "/third_party/android_tools/sdk/tools": {
       "packages": [
           {
-            "package": "flutter/android/sdk/tools/${{platform}}",
+            "package": "flutter/android/sdk/tools/${{os}}-amd64",
             "version": "version:26.1.1"
           }
       ],
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
index c61d41a..f5def03 100644
--- a/build/config/android/config.gni
+++ b/build/config/android/config.gni
@@ -26,6 +26,9 @@
   # architecture, which is different than the names GN uses.
   if (host_cpu == "x64" || host_cpu == "x86") {
     android_host_arch = "x86_64"
+  } else if (host_cpu == "arm64") {
+    # Run existing Android toolchain via Rosetta.
+    android_host_arch = "x86_64"
   } else {
     assert(false, "Need Android toolchain support for your build CPU arch.")
   }
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_key_to_constructors.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_key_to_constructors.dart
index c308c1d..7ebfe8c 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/add_key_to_constructors.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_key_to_constructors.dart
@@ -175,15 +175,26 @@
           argument is NamedExpression && argument.name.label.name == 'key');
       if (existing == null) {
         // There is no 'key' argument, so add it.
-        if (arguments.isEmpty) {
-          builder.addSimpleInsertion(
-              argumentList.leftParenthesis.end, 'key: key');
-        } else {
-          // This case should never happen because 'key' is the only parameter
-          // in the constructors for both `StatelessWidget` and `StatefulWidget`.
-          builder.addSimpleInsertion(
-              argumentList.leftParenthesis.end, 'key: key, ');
-        }
+        var namedArguments = arguments.whereType<NamedExpression>();
+        var firstNamed = namedArguments.firstOrNull;
+        var token = firstNamed?.beginToken ?? argumentList.endToken;
+        var comma = token.previous?.type == TokenType.COMMA;
+
+        builder.addInsertion(token.offset, (builder) {
+          if (arguments.length != namedArguments.length) {
+            // there are unnamed arguments
+            if (!comma) {
+              builder.write(',');
+            }
+            builder.write(' ');
+          }
+          builder.write('key: key');
+          if (firstNamed != null) {
+            builder.write(', ');
+          } else if (comma) {
+            builder.write(',');
+          }
+        });
       } else {
         // There is an existing 'key' argument, so we leave it alone.
       }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_key_to_constructors_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_key_to_constructors_test.dart
index 834a76c..1d48dd5 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_key_to_constructors_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_key_to_constructors_test.dart
@@ -13,6 +13,8 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(AddKeyToConstructorsTest);
+    defineReflectiveTests(
+        AddKeyToConstructorsWithoutNamedArgumentsAnywhereTest);
   });
 }
 
@@ -169,19 +171,93 @@
     await resolveTestCode('''
 import 'package:flutter/material.dart';
 
-class MyWidget extends StatelessWidget {
+class A extends StatelessWidget {
+  const A({required this.text, Key? key}) : super(key: key);
+
+  final String text;
+}
+
+class MyWidget extends A {
   MyWidget() : super(text: '');
 }
 ''');
     await assertHasFix('''
 import 'package:flutter/material.dart';
 
-class MyWidget extends StatelessWidget {
+class A extends StatelessWidget {
+  const A({required this.text, Key? key}) : super(key: key);
+
+  final String text;
+}
+
+class MyWidget extends A {
   MyWidget({Key? key}) : super(key: key, text: '');
 }
 ''', errorFilter: (error) => error.errorCode is LintCode);
   }
 
+  Future<void>
+      test_constructor_noParameters_withSuper_nonEmpty_tailingComma() async {
+    await resolveTestCode('''
+import 'package:flutter/material.dart';
+
+class A extends StatelessWidget {
+  const A({required this.text, Key? key}) : super(key: key);
+
+  final String text;
+}
+
+class MyWidget extends A {
+  MyWidget() : super(text: '',);
+}
+''');
+    await assertHasFix('''
+import 'package:flutter/material.dart';
+
+class A extends StatelessWidget {
+  const A({required this.text, Key? key}) : super(key: key);
+
+  final String text;
+}
+
+class MyWidget extends A {
+  MyWidget({Key? key}) : super(key: key, text: '',);
+}
+''', errorFilter: (error) => error.errorCode is LintCode);
+  }
+
+  Future<void>
+      test_constructor_noParameters_withSuper_nonNamed_trailingComma() async {
+    await resolveTestCode('''
+import 'package:flutter/material.dart';
+
+class A extends StatelessWidget {
+  const A(this.widget, {Key? key}) : super(key: key);
+
+  final Widget widget;
+}
+
+class B extends A {
+  B() : super(const Text(''),);
+}
+''');
+    await assertHasFix('''
+import 'package:flutter/material.dart';
+
+class A extends StatelessWidget {
+  const A(this.widget, {Key? key}) : super(key: key);
+
+  final Widget widget;
+}
+
+class B extends A {
+  B({Key? key}) : super(const Text(''), key: key,);
+}
+''',
+        //TODO(asashour) there should be no other errors
+        errorFilter: (error) => error.errorCode is LintCode);
+  }
+
   Future<void> test_initializer_final_constant() async {
     await resolveTestCode('''
 import 'package:flutter/material.dart';
@@ -311,3 +387,55 @@
 ''', errorFilter: (error) => error.errorCode is LintCode);
   }
 }
+
+@reflectiveTest
+class AddKeyToConstructorsWithoutNamedArgumentsAnywhereTest
+    extends FixProcessorLintTest {
+  @override
+  FixKind get kind => DartFixKind.ADD_KEY_TO_CONSTRUCTORS;
+
+  @override
+  String get lintCode => LintNames.use_key_in_widget_constructors;
+
+  @override
+  String get testPackageLanguageVersion => '2.16';
+
+  @override
+  void setUp() {
+    super.setUp();
+    writeTestPackageConfig(
+      flutter: true,
+    );
+  }
+
+  Future<void> test_constructor_noParameters_withSuper_nonEmpty() async {
+    await resolveTestCode('''
+import 'package:flutter/material.dart';
+
+class A extends StatelessWidget {
+  const A(this.widget, {Key? key}) : super(key: key);
+
+  final Widget widget;
+}
+
+class B extends A {
+  B() : super(const Text(''));
+}
+''');
+    await assertHasFix('''
+import 'package:flutter/material.dart';
+
+class A extends StatelessWidget {
+  const A(this.widget, {Key? key}) : super(key: key);
+
+  final Widget widget;
+}
+
+class B extends A {
+  B({Key? key}) : super(const Text(''), key: key);
+}
+''',
+        //TODO(asashour) there should be no other errors
+        errorFilter: (error) => error.errorCode is LintCode);
+  }
+}
diff --git a/pkg/analyzer/lib/dart/sdk/build_sdk_summary.dart b/pkg/analyzer/lib/dart/sdk/build_sdk_summary.dart
index 9451d5c..4cebed9 100644
--- a/pkg/analyzer/lib/dart/sdk/build_sdk_summary.dart
+++ b/pkg/analyzer/lib/dart/sdk/build_sdk_summary.dart
@@ -22,6 +22,7 @@
 import 'package:analyzer/src/summary2/linked_element_factory.dart';
 import 'package:analyzer/src/summary2/package_bundle_format.dart';
 import 'package:analyzer/src/summary2/reference.dart';
+import 'package:analyzer/src/util/performance/operation_performance.dart';
 import 'package:pub_semver/pub_semver.dart';
 import 'package:yaml/yaml.dart';
 
@@ -106,7 +107,11 @@
       Reference.root(),
     );
 
-    var linkResult = await link(elementFactory, inputLibraries);
+    var linkResult = await link2(
+      elementFactory: elementFactory,
+      inputLibraries: inputLibraries,
+      performance: OperationPerformanceImpl('link'),
+    );
 
     var bundleBuilder = PackageBundleBuilder();
     for (var library in inputLibraries) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index 311c3b0..ea279e3 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -26,6 +26,7 @@
 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/util/performance/operation_performance.dart';
 import 'package:path/src/context.dart';
 
 /// Context information necessary to analyze one or more libraries within an
@@ -203,8 +204,12 @@
 
         LinkResult linkResult;
         try {
-          linkResult = await link(elementFactory, inputLibraries,
-              macroExecutor: macroExecutor);
+          linkResult = await link2(
+            elementFactory: elementFactory,
+            performance: OperationPerformanceImpl('link'),
+            inputLibraries: inputLibraries,
+            macroExecutor: macroExecutor,
+          );
           librariesLinked += cycle.libraries.length;
         } catch (exception, stackTrace) {
           _throwLibraryCycleLinkException(cycle, exception, stackTrace);
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index e333fc8..efb1059 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -916,7 +916,17 @@
         }
         inputsTimer.stop();
 
-        var linkResult = await link(elementFactory, inputLibraries);
+        var linkResult = await performance.runAsync(
+          'link',
+          (performance) async {
+            return await link2(
+              elementFactory: elementFactory,
+              performance: performance,
+              inputLibraries: inputLibraries,
+            );
+          },
+        );
+
         librariesLinked += cycle.libraries.length;
 
         resolutionBytes = linkResult.resolutionBytes;
diff --git a/pkg/analyzer/lib/src/summary2/library_builder.dart b/pkg/analyzer/lib/src/summary2/library_builder.dart
index acef1f4..7594b79 100644
--- a/pkg/analyzer/lib/src/summary2/library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/library_builder.dart
@@ -24,6 +24,7 @@
 import 'package:analyzer/src/summary2/reference_resolver.dart';
 import 'package:analyzer/src/summary2/scope.dart';
 import 'package:analyzer/src/summary2/types_builder.dart';
+import 'package:analyzer/src/util/performance/operation_performance.dart';
 
 class ImplicitEnumNodes {
   final EnumElementImpl element;
@@ -275,14 +276,30 @@
     ];
   }
 
-  Future<void> executeMacroTypesPhase() async {
+  Future<void> executeMacroTypesPhase({
+    required OperationPerformanceImpl performance,
+  }) async {
     final macroApplier = _macroApplier;
     if (macroApplier == null) {
       return;
     }
 
-    await macroApplier.buildApplications();
-    var augmentationLibrary = await macroApplier.executeTypesPhase();
+    await performance.runAsync(
+      'buildApplications',
+      (performance) async {
+        await macroApplier.buildApplications(
+          performance: performance,
+        );
+      },
+    );
+
+    final augmentationLibrary = await performance.runAsync(
+      'executeTypesPhase',
+      (performance) async {
+        return await macroApplier.executeTypesPhase();
+      },
+    );
+
     if (augmentationLibrary == null) {
       return;
     }
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index 31000d1..f6e224f 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -25,15 +25,35 @@
 import 'package:analyzer/src/summary2/type_alias.dart';
 import 'package:analyzer/src/summary2/types_builder.dart';
 import 'package:analyzer/src/summary2/variance_builder.dart';
+import 'package:analyzer/src/util/performance/operation_performance.dart';
 
 /// Note that AST units and tokens of [inputLibraries] will be damaged.
+@Deprecated('Use link2() instead')
 Future<LinkResult> link(
   LinkedElementFactory elementFactory,
   List<LinkInputLibrary> inputLibraries, {
   macro.MultiMacroExecutor? macroExecutor,
+  OperationPerformanceImpl? performance,
 }) async {
-  var linker = Linker(elementFactory, macroExecutor);
-  await linker.link(inputLibraries);
+  return await link2(
+    elementFactory: elementFactory,
+    inputLibraries: inputLibraries,
+    performance: OperationPerformanceImpl('<root>'),
+  );
+}
+
+/// Note that AST units and tokens of [inputLibraries] will be damaged.
+Future<LinkResult> link2({
+  required LinkedElementFactory elementFactory,
+  required OperationPerformanceImpl performance,
+  required List<LinkInputLibrary> inputLibraries,
+  macro.MultiMacroExecutor? macroExecutor,
+}) async {
+  final linker = Linker(elementFactory, macroExecutor);
+  await linker.link(
+    performance: performance,
+    inputLibraries: inputLibraries,
+  );
   return LinkResult(
     resolutionBytes: linker.resolutionBytes,
     macroGeneratedUnits: linker.macroGeneratedUnits,
@@ -79,12 +99,18 @@
     return elementNodes[element];
   }
 
-  Future<void> link(List<LinkInputLibrary> inputLibraries) async {
+  Future<void> link({
+    required OperationPerformanceImpl performance,
+    required List<LinkInputLibrary> inputLibraries,
+  }) async {
     for (var inputLibrary in inputLibraries) {
       LibraryBuilder.build(this, inputLibrary);
     }
 
-    await _buildOutlines();
+    await _buildOutlines(
+      performance: performance,
+    );
+
     _writeLibraries();
   }
 
@@ -94,13 +120,31 @@
     }
   }
 
-  Future<void> _buildOutlines() async {
+  Future<void> _buildOutlines({
+    required OperationPerformanceImpl performance,
+  }) async {
     _createTypeSystemIfNotLinkingDartCore();
-    await _computeLibraryScopes();
+
+    await performance.runAsync(
+      'computeLibraryScopes',
+      (performance) async {
+        await _computeLibraryScopes(
+          performance: performance,
+        );
+      },
+    );
+
     _createTypeSystem();
     _resolveTypes();
     _buildEnumChildren();
-    await _executeMacroDeclarationsPhase();
+
+    await performance.runAsync(
+      'executeMacroDeclarationsPhase',
+      (_) async {
+        await _executeMacroDeclarationsPhase();
+      },
+    );
+
     SuperConstructorResolver(this).perform();
     _performTopLevelInference();
     _resolveConstructors();
@@ -117,14 +161,23 @@
     }
   }
 
-  Future<void> _computeLibraryScopes() async {
+  Future<void> _computeLibraryScopes({
+    required OperationPerformanceImpl performance,
+  }) async {
     for (var library in builders.values) {
       library.buildElements();
     }
 
-    for (var library in builders.values) {
-      await library.executeMacroTypesPhase();
-    }
+    await performance.runAsync(
+      'executeMacroTypesPhase',
+      (performance) async {
+        for (var library in builders.values) {
+          await library.executeMacroTypesPhase(
+            performance: performance,
+          );
+        }
+      },
+    );
 
     macroDeclarationBuilder.transferToElements();
 
diff --git a/pkg/analyzer/lib/src/summary2/macro_application.dart b/pkg/analyzer/lib/src/summary2/macro_application.dart
index 8ca3caf..24e180b 100644
--- a/pkg/analyzer/lib/src/summary2/macro_application.dart
+++ b/pkg/analyzer/lib/src/summary2/macro_application.dart
@@ -20,6 +20,7 @@
 import 'package:analyzer/src/summary2/linked_element_factory.dart';
 import 'package:analyzer/src/summary2/macro_application_error.dart';
 import 'package:analyzer/src/summary2/macro_declarations.dart';
+import 'package:analyzer/src/util/performance/operation_performance.dart';
 
 class LibraryMacroApplier {
   final MultiMacroExecutor macroExecutor;
@@ -47,7 +48,9 @@
   Linker get _linker => libraryBuilder.linker;
 
   /// Fill [_targets]s with macro applications.
-  Future<void> buildApplications() async {
+  Future<void> buildApplications({
+    required OperationPerformanceImpl performance,
+  }) async {
     final collector = _MacroTargetElementCollector();
     libraryBuilder.element.accept(collector);
 
@@ -55,11 +58,17 @@
       final targetNode = _linker.elementNodes[targetElement];
       // TODO(scheglov) support other declarations
       if (targetNode is ClassDeclaration) {
-        await _buildApplications(
-          targetElement,
-          targetNode.metadata,
-          macro.DeclarationKind.clazz,
-          () => declarationBuilder.fromNode.classDeclaration(targetNode),
+        await performance.runAsync(
+          'forClassDeclaration',
+          (performance) async {
+            await _buildApplications(
+              targetElement,
+              targetNode.metadata,
+              macro.DeclarationKind.clazz,
+              () => declarationBuilder.fromNode.classDeclaration(targetNode),
+              performance: performance,
+            );
+          },
         );
       }
     }
@@ -117,8 +126,9 @@
     MacroTargetElement targetElement,
     List<Annotation> annotations,
     macro.DeclarationKind declarationKind,
-    macro.DeclarationImpl Function() getDeclaration,
-  ) async {
+    macro.DeclarationImpl Function() getDeclaration, {
+    required OperationPerformanceImpl performance,
+  }) async {
     final applications = <_MacroApplication>[];
 
     for (var i = 0; i < annotations.length; i++) {
@@ -136,12 +146,14 @@
                 annotationIndex: i,
                 node: argumentsNode,
               );
-              return await macroExecutor.instantiate(
-                libraryUri: macroClass.librarySource.uri,
-                className: macroClass.name,
-                constructorName: constructorName,
-                arguments: arguments,
-              );
+              return await performance.runAsync('instantiate', (_) {
+                return macroExecutor.instantiate(
+                  libraryUri: macroClass.librarySource.uri,
+                  className: macroClass.name,
+                  constructorName: constructorName,
+                  arguments: arguments,
+                );
+              });
             },
             annotationIndex: i,
             onError: (error) {
diff --git a/pkg/analyzer/lib/src/util/performance/operation_performance.dart b/pkg/analyzer/lib/src/util/performance/operation_performance.dart
index 3d5ac61b..b3f6b38 100644
--- a/pkg/analyzer/lib/src/util/performance/operation_performance.dart
+++ b/pkg/analyzer/lib/src/util/performance/operation_performance.dart
@@ -105,6 +105,12 @@
     );
   }
 
+  /// Collapse any children into this operation, making [elapsedSelf] equal
+  /// to [elapsed].
+  void collapse() {
+    _children.clear();
+  }
+
   @override
   OperationPerformanceImpl? getChild(String name) {
     return _children.firstWhereOrNull(
diff --git a/pkg/analyzer/test/src/summary/elements_base.dart b/pkg/analyzer/test/src/summary/elements_base.dart
index 16267e1..3fd14b1 100644
--- a/pkg/analyzer/test/src/summary/elements_base.dart
+++ b/pkg/analyzer/test/src/summary/elements_base.dart
@@ -31,6 +31,7 @@
 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/performance/operation_performance.dart';
 import 'package:analyzer/src/util/uri.dart';
 import 'package:meta/meta.dart';
 import 'package:path/path.dart' as package_path;
@@ -103,7 +104,11 @@
       Reference.root(),
     );
 
-    var sdkLinkResult = await link(elementFactory, inputLibraries);
+    var sdkLinkResult = await link2(
+      elementFactory: elementFactory,
+      inputLibraries: inputLibraries,
+      performance: OperationPerformanceImpl('link'),
+    );
 
     return _sdkBundle = _SdkBundle(
       resolutionBytes: sdkLinkResult.resolutionBytes,
@@ -128,75 +133,99 @@
     bool dumpSummaries = false,
     List<Set<String>>? preBuildSequence,
   }) async {
-    _buildSourceFactory();
+    final performance = OperationPerformanceImpl('<root>');
+    final result = await performance.runAsync(
+      'buildLibrary',
+      (performance) async {
+        _buildSourceFactory();
 
-    var testFile = newFile(testFilePath, text);
-    var testUri = sourceFactory.pathToUri(testFile.path)!;
-    var testSource = sourceFactory.forUri2(testUri)!;
+        var testFile = newFile(testFilePath, text);
+        var testUri = sourceFactory.pathToUri(testFile.path)!;
+        var testSource = sourceFactory.forUri2(testUri)!;
 
-    var inputLibraries = <LinkInputLibrary>[];
-    _addNonDartLibraries({}, inputLibraries, testSource);
+        var inputLibraries = <LinkInputLibrary>[];
+        _addNonDartLibraries({}, inputLibraries, testSource);
 
-    var unitsInformativeBytes = <Uri, Uint8List>{};
-    for (var inputLibrary in inputLibraries) {
-      for (var inputUnit in inputLibrary.units) {
-        var informativeBytes = writeUnitInformative(inputUnit.unit);
-        unitsInformativeBytes[inputUnit.uri] = informativeBytes;
-      }
-    }
+        var unitsInformativeBytes = <Uri, Uint8List>{};
+        for (var inputLibrary in inputLibraries) {
+          for (var inputUnit in inputLibrary.units) {
+            var informativeBytes = writeUnitInformative(inputUnit.unit);
+            unitsInformativeBytes[inputUnit.uri] = informativeBytes;
+          }
+        }
 
-    var analysisContext = AnalysisContextImpl(
-      SynchronousSession(
-        AnalysisOptionsImpl()..contextFeatures = featureSet,
-        declaredVariables,
-      ),
-      sourceFactory,
+        var analysisContext = AnalysisContextImpl(
+          SynchronousSession(
+            AnalysisOptionsImpl()..contextFeatures = featureSet,
+            declaredVariables,
+          ),
+          sourceFactory,
+        );
+
+        var elementFactory = LinkedElementFactory(
+          analysisContext,
+          _AnalysisSessionForLinking(),
+          Reference.root(),
+        );
+        elementFactory.addBundle(
+          BundleReader(
+            elementFactory: elementFactory,
+            unitsInformativeBytes: {},
+            resolutionBytes: (await sdkBundle).resolutionBytes,
+          ),
+        );
+
+        await performance.runAsync(
+          'linkConfiguredLibraries',
+          (performance) async {
+            await _linkConfiguredLibraries(
+              elementFactory,
+              inputLibraries,
+              preBuildSequence,
+              performance,
+            );
+          },
+        );
+
+        var linkResult = await performance.runAsync(
+          'link',
+          (performance) async {
+            return await link2(
+              elementFactory: elementFactory,
+              inputLibraries: inputLibraries,
+              macroExecutor: _macroExecutor,
+              performance: performance,
+            );
+          },
+        );
+
+        for (var macroUnit in linkResult.macroGeneratedUnits) {
+          var informativeBytes = writeUnitInformative(macroUnit.unit);
+          unitsInformativeBytes[macroUnit.uri] = informativeBytes;
+        }
+
+        if (!keepLinkingLibraries) {
+          elementFactory.removeBundle(
+            inputLibraries.map((e) => e.uriStr).toSet(),
+          );
+          elementFactory.addBundle(
+            BundleReader(
+              elementFactory: elementFactory,
+              unitsInformativeBytes: unitsInformativeBytes,
+              resolutionBytes: linkResult.resolutionBytes,
+            ),
+          );
+        }
+
+        return elementFactory.libraryOfUri2('$testUri');
+      },
     );
 
-    var elementFactory = LinkedElementFactory(
-      analysisContext,
-      _AnalysisSessionForLinking(),
-      Reference.root(),
-    );
-    elementFactory.addBundle(
-      BundleReader(
-        elementFactory: elementFactory,
-        unitsInformativeBytes: {},
-        resolutionBytes: (await sdkBundle).resolutionBytes,
-      ),
-    );
+    // final performanceBuffer = StringBuffer();
+    // performance.children.single.write(buffer: performanceBuffer);
+    // print(performanceBuffer);
 
-    await _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(
-        inputLibraries.map((e) => e.uriStr).toSet(),
-      );
-      elementFactory.addBundle(
-        BundleReader(
-          elementFactory: elementFactory,
-          unitsInformativeBytes: unitsInformativeBytes,
-          resolutionBytes: linkResult.resolutionBytes,
-        ),
-      );
-    }
-
-    return elementFactory.libraryOfUri2('$testUri');
+    return result;
   }
 
   @mustCallSuper
@@ -366,6 +395,7 @@
     LinkedElementFactory elementFactory,
     List<LinkInputLibrary> inputLibraries,
     List<Set<String>>? uriStrSetList,
+    OperationPerformanceImpl performance,
   ) async {
     if (uriStrSetList == null) {
       return;
@@ -381,13 +411,19 @@
         }
       }
 
-      await link(
-        elementFactory,
-        cycleInputLibraries,
-        macroExecutor: _macroExecutor,
-      );
+      await performance.runAsync('link', (performance) async {
+        await link2(
+          elementFactory: elementFactory,
+          inputLibraries: cycleInputLibraries,
+          macroExecutor: _macroExecutor,
+          performance: performance,
+        );
+        performance.collapse();
+      });
 
-      await _buildMacroLibraries(elementFactory, macroLibraries);
+      await performance.runAsync('buildMacroLibraries', (_) async {
+        await _buildMacroLibraries(elementFactory, macroLibraries);
+      });
 
       // Remove libraries that we just linked.
       cycleInputLibraries.forEach(inputLibraries.remove);
diff --git a/pkg/dart2native/lib/macho.dart b/pkg/dart2native/lib/macho.dart
index e0d8f93..9294483 100644
--- a/pkg/dart2native/lib/macho.dart
+++ b/pkg/dart2native/lib/macho.dart
@@ -6,6 +6,8 @@
 // part of the Apple system headers. All comments, which detail the format of
 // Mach-O files, have been reproduced from the orginal header.
 
+// ignore_for_file: non_constant_identifier_names, constant_identifier_names
+
 import 'dart:io';
 import 'dart:typed_data';
 
@@ -87,6 +89,7 @@
     return _data > other;
   }
 
+  @override
   bool operator ==(other) {
     if (other is Uint64) {
       return _data == other._data;
@@ -94,6 +97,9 @@
       return false;
     }
   }
+
+  @override
+  int get hashCode => _data.hashCode;
 }
 
 class Int32 extends IntLike {
@@ -103,6 +109,7 @@
     return Int32(_data | other._data);
   }
 
+  @override
   bool operator ==(other) {
     if (other is Int32) {
       return _data == other._data;
@@ -110,6 +117,9 @@
       return false;
     }
   }
+
+  @override
+  int get hashCode => _data.hashCode;
 }
 
 class Uint16 extends IntLike {
@@ -147,6 +157,7 @@
     return _data >= other;
   }
 
+  @override
   bool operator ==(other) {
     if (other is Uint32) {
       return _data == other._data;
@@ -155,6 +166,9 @@
     }
   }
 
+  @override
+  int get hashCode => _data.hashCode;
+
   Uint64 asUint64() {
     return Uint64(_data);
   }
@@ -420,9 +434,9 @@
     stream.writeUint32(nsects);
     stream.writeUint32(flags);
 
-    sections.forEach((section) {
+    for (final section in sections) {
       section.writeContentsSync(stream);
-    });
+    }
   }
 }
 
diff --git a/pkg/dart2native/lib/macho_parser.dart b/pkg/dart2native/lib/macho_parser.dart
index 20deb1d..99dce1a 100644
--- a/pkg/dart2native/lib/macho_parser.dart
+++ b/pkg/dart2native/lib/macho_parser.dart
@@ -261,9 +261,9 @@
     }
 
     // Write all of the commands.
-    commands.forEach((command) {
+    for (var command in commands) {
       writeLoadCommandToStream(command, stream);
-    });
+    }
 
     // Pad the header according to the offset.
     final int paddingAmount = headerMaxOffset - stream.positionSync();
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index e71c21bf..6debbc9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -2030,23 +2030,15 @@
     }
     TypeConstraintGatherer? gatherer;
     if (inferenceNeeded) {
-      inferredTypes = [const UnknownType()];
       gatherer = inferrer.typeSchemaEnvironment.setupGenericTypeInference(
           listType,
           listClass.typeParameters,
           typeContext,
           inferrer.libraryBuilder.library,
           isConst: node.isConst);
-      inferrer.typeSchemaEnvironment.partialInfer(
-          gatherer,
-          listClass.typeParameters,
-          inferredTypes,
-          inferrer.libraryBuilder.library);
+      inferredTypes = inferrer.typeSchemaEnvironment.partialInfer(gatherer,
+          listClass.typeParameters, null, inferrer.libraryBuilder.library);
       inferredTypeArgument = inferredTypes[0];
-      if (inferrer.dataForTesting != null) {
-        inferrer.dataForTesting!.typeInferenceResult
-            .inferredTypeArguments[node] = inferredTypes;
-      }
     } else {
       inferredTypeArgument = node.typeArgument;
     }
@@ -2068,11 +2060,15 @@
     }
     if (inferenceNeeded) {
       gatherer!.constrainArguments(formalTypes!, actualTypes!);
-      inferrer.typeSchemaEnvironment.upwardsInfer(
+      inferredTypes = inferrer.typeSchemaEnvironment.upwardsInfer(
           gatherer,
           listClass.typeParameters,
           inferredTypes!,
           inferrer.libraryBuilder.library);
+      if (inferrer.dataForTesting != null) {
+        inferrer.dataForTesting!.typeInferenceResult
+            .inferredTypeArguments[node] = inferredTypes;
+      }
       inferredTypeArgument = inferredTypes[0];
       inferrer.instrumentation?.record(
           inferrer.uriForInstrumentation,
@@ -2715,24 +2711,16 @@
     }
     TypeConstraintGatherer? gatherer;
     if (inferenceNeeded) {
-      inferredTypes = [noInferredType, noInferredType];
       gatherer = inferrer.typeSchemaEnvironment.setupGenericTypeInference(
           mapType,
           mapClass.typeParameters,
           typeContext,
           inferrer.libraryBuilder.library,
           isConst: node.isConst);
-      inferrer.typeSchemaEnvironment.partialInfer(
-          gatherer,
-          mapClass.typeParameters,
-          inferredTypes,
-          inferrer.libraryBuilder.library);
+      inferredTypes = inferrer.typeSchemaEnvironment.partialInfer(gatherer,
+          mapClass.typeParameters, null, inferrer.libraryBuilder.library);
       inferredKeyType = inferredTypes[0];
       inferredValueType = inferredTypes[1];
-      if (inferrer.dataForTesting != null) {
-        inferrer.dataForTesting!.typeInferenceResult
-            .inferredTypeArguments[node] = inferredTypes;
-      }
     } else {
       inferredKeyType = node.keyType;
       inferredValueType = node.valueType;
@@ -2796,7 +2784,6 @@
           formalTypesForSet.add(setType.typeArguments[0]);
         }
 
-        List<DartType> inferredTypesForSet = <DartType>[noInferredType];
         // Note: we don't use the previously created gatherer because it was set
         // up presuming that the literal would be a map; we now know that it
         // needs to be a set.
@@ -2807,13 +2794,11 @@
                 typeContext,
                 inferrer.libraryBuilder.library,
                 isConst: node.isConst);
-        inferrer.typeSchemaEnvironment.partialInfer(
-            gatherer,
-            inferrer.coreTypes.setClass.typeParameters,
-            inferredTypesForSet,
-            inferrer.libraryBuilder.library);
+        List<DartType> inferredTypesForSet = inferrer.typeSchemaEnvironment
+            .partialInfer(gatherer, inferrer.coreTypes.setClass.typeParameters,
+                null, inferrer.libraryBuilder.library);
         gatherer.constrainArguments(formalTypesForSet, actualTypesForSet!);
-        inferrer.typeSchemaEnvironment.upwardsInfer(
+        inferredTypesForSet = inferrer.typeSchemaEnvironment.upwardsInfer(
             gatherer,
             inferrer.coreTypes.setClass.typeParameters,
             inferredTypesForSet,
@@ -2864,11 +2849,15 @@
             replacement);
       }
       gatherer!.constrainArguments(formalTypes!, actualTypes!);
-      inferrer.typeSchemaEnvironment.upwardsInfer(
+      inferredTypes = inferrer.typeSchemaEnvironment.upwardsInfer(
           gatherer,
           mapClass.typeParameters,
           inferredTypes!,
           inferrer.libraryBuilder.library);
+      if (inferrer.dataForTesting != null) {
+        inferrer.dataForTesting!.typeInferenceResult
+            .inferredTypeArguments[node] = inferredTypes;
+      }
       inferredKeyType = inferredTypes[0];
       inferredValueType = inferredTypes[1];
       inferrer.instrumentation?.record(
@@ -5985,23 +5974,15 @@
     }
     TypeConstraintGatherer? gatherer;
     if (inferenceNeeded) {
-      inferredTypes = [const UnknownType()];
       gatherer = inferrer.typeSchemaEnvironment.setupGenericTypeInference(
           setType,
           setClass.typeParameters,
           typeContext,
           inferrer.libraryBuilder.library,
           isConst: node.isConst);
-      inferrer.typeSchemaEnvironment.partialInfer(
-          gatherer,
-          setClass.typeParameters,
-          inferredTypes,
-          inferrer.libraryBuilder.library);
+      inferredTypes = inferrer.typeSchemaEnvironment.partialInfer(gatherer,
+          setClass.typeParameters, null, inferrer.libraryBuilder.library);
       inferredTypeArgument = inferredTypes[0];
-      if (inferrer.dataForTesting != null) {
-        inferrer.dataForTesting!.typeInferenceResult
-            .inferredTypeArguments[node] = inferredTypes;
-      }
     } else {
       inferredTypeArgument = node.typeArgument;
     }
@@ -6023,11 +6004,15 @@
     }
     if (inferenceNeeded) {
       gatherer!.constrainArguments(formalTypes!, actualTypes!);
-      inferrer.typeSchemaEnvironment.upwardsInfer(
+      inferredTypes = inferrer.typeSchemaEnvironment.upwardsInfer(
           gatherer,
           setClass.typeParameters,
           inferredTypes!,
           inferrer.libraryBuilder.library);
+      if (inferrer.dataForTesting != null) {
+        inferrer.dataForTesting!.typeInferenceResult
+            .inferredTypeArguments[node] = inferredTypes;
+      }
       inferredTypeArgument = inferredTypes[0];
       inferrer.instrumentation?.record(
           inferrer.uriForInstrumentation,
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 4f37948..609515e 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -128,6 +128,8 @@
     for (_DeferredParamInfo functionLiteral in deferredFunctionLiterals)
       functionLiteral.evaluationOrderIndex
   };
+  assert(evaluationOrderIndicesAlreadyCovered
+      .every((i) => 0 <= i && i < formalTypes.length));
   return [
     for (int i = 0; i < formalTypes.length; i++)
       if (!evaluationOrderIndicesAlreadyCovered.contains(i))
@@ -976,7 +978,7 @@
         typeSchemaEnvironment.setupGenericTypeInference(
             null, typeParameters, null, libraryBuilder.library);
     gatherer.constrainArguments([onType], [receiverType]);
-    typeSchemaEnvironment.upwardsInfer(
+    inferredTypes = typeSchemaEnvironment.upwardsInfer(
         gatherer, typeParameters, inferredTypes, libraryBuilder.library);
     return inferredTypes;
   }
@@ -2376,8 +2378,6 @@
                     : coreTypes.objectLegacyRawType)
             .substituteType(typeContext);
       }
-      inferredTypes = new List<DartType>.filled(
-          calleeTypeParameters.length, const UnknownType());
       gatherer = typeSchemaEnvironment.setupGenericTypeInference(
           isNonNullableByDefault
               ? calleeType.returnType
@@ -2385,8 +2385,8 @@
           calleeTypeParameters,
           typeContext,
           libraryBuilder.library);
-      typeSchemaEnvironment.partialInfer(gatherer, calleeTypeParameters,
-          inferredTypes, libraryBuilder.library);
+      inferredTypes = typeSchemaEnvironment.partialInfer(
+          gatherer, calleeTypeParameters, null, libraryBuilder.library);
       substitution =
           Substitution.fromPairs(calleeTypeParameters, inferredTypes);
     } else if (explicitTypeArguments != null &&
@@ -2527,7 +2527,9 @@
             argumentExpression: argumentExpression,
             unparenthesizedExpression: unparenthesizedExpression,
             isNamed: !isExpression,
-            evaluationOrderIndex: evaluationOrderIndex,
+            evaluationOrderIndex: isImplicitExtensionMember
+                ? evaluationOrderIndex - 1
+                : evaluationOrderIndex,
             index: index));
         // We don't have `identical` info yet, so fill it in with `null` for
         // now.  Later, when we visit the function literal, we'll replace it.
@@ -2575,8 +2577,8 @@
                   : const [])
           .planReconciliationStages()) {
         if (gatherer != null && !isFirstStage) {
-          typeSchemaEnvironment.partialInfer(gatherer, calleeTypeParameters,
-              inferredTypes!, libraryBuilder.library);
+          inferredTypes = typeSchemaEnvironment.partialInfer(gatherer,
+              calleeTypeParameters, inferredTypes, libraryBuilder.library);
           substitution =
               Substitution.fromPairs(calleeTypeParameters, inferredTypes);
         }
@@ -2702,8 +2704,8 @@
     }
 
     if (inferenceNeeded) {
-      typeSchemaEnvironment.upwardsInfer(gatherer!, calleeTypeParameters,
-          inferredTypes!, libraryBuilder.library);
+      inferredTypes = typeSchemaEnvironment.upwardsInfer(gatherer!,
+          calleeTypeParameters, inferredTypes!, libraryBuilder.library);
       assert(inferredTypes.every((type) => isKnown(type)),
           "Unknown type(s) in inferred types: $inferredTypes.");
       assert(inferredTypes.every((type) => !hasPromotedTypeVariable(type)),
@@ -4251,7 +4253,7 @@
         TypeConstraintGatherer gatherer =
             typeSchemaEnvironment.setupGenericTypeInference(instantiatedType,
                 typeParameters, context, libraryBuilder.library);
-        typeSchemaEnvironment.upwardsInfer(
+        inferredTypes = typeSchemaEnvironment.upwardsInfer(
             gatherer, typeParameters, inferredTypes, libraryBuilder.library);
         Substitution substitution =
             Substitution.fromPairs(typeParameters, inferredTypes);
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart b/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
index 86cc5da..dd2f233 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
@@ -130,14 +130,14 @@
 
   /// Performs partial (either downwards or horizontal) inference, producing a
   /// set of inferred types that may contain references to the "unknown type".
-  void partialInfer(
+  List<DartType> partialInfer(
           TypeConstraintGatherer gatherer,
           List<TypeParameter> typeParametersToInfer,
-          List<DartType> inferredTypes,
+          List<DartType>? previouslyInferredTypes,
           Library clientLibrary) =>
-      _chooseTypes(
-          gatherer, typeParametersToInfer, inferredTypes, clientLibrary,
-          downwardsInferPhase: true);
+      _chooseTypes(gatherer, typeParametersToInfer, previouslyInferredTypes,
+          clientLibrary,
+          partial: true);
 
   @override
   DartType getTypeOfSpecialCasedBinaryOperator(DartType type1, DartType type2,
@@ -255,26 +255,24 @@
   /// Use the given [constraints] to substitute for type variables.
   ///
   /// [typeParametersToInfer] is the set of type parameters that should be
-  /// substituted for.  [inferredTypes] should be a list of the same length.
+  /// substituted for.  [previouslyInferredTypes], if present, should be the set
+  /// of types inferred by the last call to this method; it should be a list of
+  /// the same length.
   ///
-  /// If [downwardsInferPhase] is `true`, then we are in the first pass of
-  /// inference, pushing context types down.  This means we are allowed to push
-  /// down `?` to precisely represent an unknown type.  [inferredTypes] should
-  /// be initially populated with `?`.  These `?`s will be replaced, if
-  /// appropriate, with the types that were inferred by downwards inference.
+  /// If [partial] is `true`, then we not in the final pass of inference.  This
+  /// means we are allowed to return `?` to precisely represent an unknown type.
   ///
-  /// If [downwardsInferPhase] is `false`, then we are in the second pass of
-  /// inference, and must not conclude `?` for any type formal.  In this pass,
-  /// [inferredTypes] should contain the values from the first pass.  They will
-  /// be replaced with the final inferred types.
-  void inferTypeFromConstraints(
+  /// If [partial] is `false`, then we are in the final pass of inference, and
+  /// must not conclude `?` for any type formal.
+  List<DartType> inferTypeFromConstraints(
       Map<TypeParameter, TypeConstraint> constraints,
       List<TypeParameter> typeParametersToInfer,
-      List<DartType> inferredTypes,
+      List<DartType>? previouslyInferredTypes,
       Library clientLibrary,
-      {bool downwardsInferPhase: false}) {
-    List<DartType>? typesFromDownwardsInference =
-        downwardsInferPhase ? null : inferredTypes.toList(growable: false);
+      {bool partial: false}) {
+    List<DartType> inferredTypes =
+        previouslyInferredTypes?.toList(growable: false) ??
+            new List.filled(typeParametersToInfer.length, const UnknownType());
 
     for (int i = 0; i < typeParametersToInfer.length; i++) {
       TypeParameter typeParam = typeParametersToInfer[i];
@@ -288,21 +286,25 @@
       }
 
       TypeConstraint constraint = constraints[typeParam]!;
-      if (downwardsInferPhase) {
+      if (partial) {
         inferredTypes[i] = _inferTypeParameterFromContext(
-            constraint, extendsConstraint, clientLibrary);
+            previouslyInferredTypes?[i],
+            constraint,
+            extendsConstraint,
+            clientLibrary,
+            isLegacyCovariant: typeParam.isLegacyCovariant);
       } else {
         inferredTypes[i] = _inferTypeParameterFromAll(
-            typesFromDownwardsInference![i],
+            previouslyInferredTypes![i],
             constraint,
             extendsConstraint,
             clientLibrary,
             isContravariant: typeParam.variance == Variance.contravariant,
-            preferUpwardsInference: !typeParam.isLegacyCovariant);
+            isLegacyCovariant: typeParam.isLegacyCovariant);
       }
     }
 
-    if (!downwardsInferPhase) {
+    if (!partial) {
       assert(typeParametersToInfer.length == inferredTypes.length);
       FreshTypeParameters freshTypeParameters =
           getFreshTypeParameters(typeParametersToInfer);
@@ -337,6 +339,8 @@
         }
       }
     }
+
+    return inferredTypes;
   }
 
   @override
@@ -502,44 +506,48 @@
 
   /// Performs upwards inference, producing a final set of inferred types that
   /// does not  contain references to the "unknown type".
-  void upwardsInfer(
+  List<DartType> upwardsInfer(
           TypeConstraintGatherer gatherer,
           List<TypeParameter> typeParametersToInfer,
-          List<DartType> inferredTypes,
+          List<DartType> previouslyInferredTypes,
           Library clientLibrary) =>
-      _chooseTypes(
-          gatherer, typeParametersToInfer, inferredTypes, clientLibrary,
-          downwardsInferPhase: false);
+      _chooseTypes(gatherer, typeParametersToInfer, previouslyInferredTypes,
+          clientLibrary,
+          partial: false);
 
   /// Computes (or recomputes) a set of [inferredTypes] based on the constraints
   /// that have been recorded so far.
-  void _chooseTypes(
+  List<DartType> _chooseTypes(
       TypeConstraintGatherer gatherer,
       List<TypeParameter> typeParametersToInfer,
-      List<DartType> inferredTypes,
+      List<DartType>? previouslyInferredTypes,
       Library clientLibrary,
-      {required bool downwardsInferPhase}) {
-    inferTypeFromConstraints(gatherer.computeConstraints(clientLibrary),
-        typeParametersToInfer, inferredTypes, clientLibrary,
-        downwardsInferPhase: downwardsInferPhase);
+      {required bool partial}) {
+    List<DartType> inferredTypes = inferTypeFromConstraints(
+        gatherer.computeConstraints(clientLibrary),
+        typeParametersToInfer,
+        previouslyInferredTypes,
+        clientLibrary,
+        partial: partial);
 
     for (int i = 0; i < inferredTypes.length; i++) {
       inferredTypes[i] = demoteTypeInLibrary(inferredTypes[i], clientLibrary);
     }
+    return inferredTypes;
   }
 
   DartType _inferTypeParameterFromAll(
-      DartType typeFromContextInference,
+      DartType typeFromPreviousInference,
       TypeConstraint constraint,
       DartType? extendsConstraint,
       Library clientLibrary,
       {bool isContravariant: false,
-      bool preferUpwardsInference: false}) {
-    // See if we already fixed this type from downwards inference.
-    // If so, then we aren't allowed to change it based on argument types unless
-    // [preferUpwardsInference] is true.
-    if (!preferUpwardsInference && isKnown(typeFromContextInference)) {
-      return typeFromContextInference;
+      bool isLegacyCovariant: true}) {
+    // See if we already fixed this type in a previous inference step.
+    // If so, then we aren't allowed to change it unless [isLegacyCovariant] is
+    // false.
+    if (isLegacyCovariant && isKnown(typeFromPreviousInference)) {
+      return typeFromPreviousInference;
     }
 
     if (extendsConstraint != null) {
@@ -559,8 +567,21 @@
         isContravariant: isContravariant);
   }
 
-  DartType _inferTypeParameterFromContext(TypeConstraint constraint,
-      DartType? extendsConstraint, Library clientLibrary) {
+  DartType _inferTypeParameterFromContext(
+      DartType? typeFromPreviousInference,
+      TypeConstraint constraint,
+      DartType? extendsConstraint,
+      Library clientLibrary,
+      {bool isLegacyCovariant: true}) {
+    // See if we already fixed this type in a previous inference step.
+    // If so, then we aren't allowed to change it unless [isLegacyCovariant] is
+    // false.
+    if (isLegacyCovariant &&
+        typeFromPreviousInference != null &&
+        isKnown(typeFromPreviousInference)) {
+      return typeFromPreviousInference;
+    }
+
     DartType t = solveTypeConstraint(
         constraint,
         clientLibrary.isNonNullableByDefault
diff --git a/pkg/front_end/test/fasta/type_inference/type_schema_environment_test_base.dart b/pkg/front_end/test/fasta/type_inference/type_schema_environment_test_base.dart
index 3309b0b..dfb95a3 100644
--- a/pkg/front_end/test/fasta/type_inference/type_schema_environment_test_base.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_schema_environment_test_base.dart
@@ -156,10 +156,9 @@
           ? null
           : functionTypeNode.positionalParameters;
 
-      List<DartType> inferredTypeNodes;
+      List<DartType>? inferredTypeNodes;
       if (inferredTypesFromDownwardPhase == null) {
-        inferredTypeNodes = new List<DartType>.generate(
-            typeParameterNodesToInfer.length, (_) => new UnknownType());
+        inferredTypeNodes = null;
       } else {
         inferredTypeNodes = parseTypes(inferredTypesFromDownwardPhase);
       }
@@ -171,12 +170,12 @@
               returnContextTypeNode,
               testLibrary);
       if (formalTypeNodes == null) {
-        typeSchemaEnvironment.partialInfer(gatherer, typeParameterNodesToInfer,
-            inferredTypeNodes, testLibrary);
+        inferredTypeNodes = typeSchemaEnvironment.partialInfer(gatherer,
+            typeParameterNodesToInfer, inferredTypeNodes, testLibrary);
       } else {
         gatherer.constrainArguments(formalTypeNodes, actualTypeNodes!);
-        typeSchemaEnvironment.upwardsInfer(gatherer, typeParameterNodesToInfer,
-            inferredTypeNodes, testLibrary);
+        inferredTypeNodes = typeSchemaEnvironment.upwardsInfer(gatherer,
+            typeParameterNodesToInfer, inferredTypeNodes!, testLibrary);
       }
 
       assert(
@@ -204,18 +203,15 @@
       TypeConstraint typeConstraint = parseConstraint(constraints);
       DartType expectedTypeNode = parseType(expected);
       TypeParameter typeParameterNode = typeParameterNodes.single;
-      List<DartType> inferredTypeNodes = <DartType>[
-        inferredTypeFromDownwardPhase == null
-            ? new UnknownType()
-            : parseType(inferredTypeFromDownwardPhase)
-      ];
+      List<DartType>? inferredTypeNodes = inferredTypeFromDownwardPhase == null
+          ? null
+          : <DartType>[parseType(inferredTypeFromDownwardPhase)];
 
-      typeSchemaEnvironment.inferTypeFromConstraints(
-          {typeParameterNode: typeConstraint},
-          [typeParameterNode],
-          inferredTypeNodes,
-          testLibrary,
-          downwardsInferPhase: downwardsInferPhase);
+      inferredTypeNodes = typeSchemaEnvironment.inferTypeFromConstraints({
+        typeParameterNode: typeConstraint
+      }, [
+        typeParameterNode
+      ], inferredTypeNodes, testLibrary, partial: downwardsInferPhase);
 
       expect(inferredTypeNodes.single, expectedTypeNode);
     });
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 83bb81c..0b2a65c 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -444,6 +444,7 @@
 nottest
 null'ed
 numerator
+nums
 ob
 obool
 observable
diff --git a/pkg/front_end/testcases/inference_update_1/downward_inference_preferred_over_horizontal.dart b/pkg/front_end/testcases/inference_update_1/downward_inference_preferred_over_horizontal.dart
new file mode 100644
index 0000000..7896c7a
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/downward_inference_preferred_over_horizontal.dart
@@ -0,0 +1,15 @@
+// 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.
+
+// Tests that when the feature is enabled, types supplied by downward inference
+// are preferred over those available via horizontal inference.
+//
+// The way this happens is that the type parameter is "fixed" after the downward
+// inference phase and is not changed in further inference phases.
+
+testProductOfNums(List<num> values) {
+  num a = values.fold(1, (p, v) => p * v);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference_update_1/downward_inference_preferred_over_horizontal.dart.textual_outline.expect b/pkg/front_end/testcases/inference_update_1/downward_inference_preferred_over_horizontal.dart.textual_outline.expect
new file mode 100644
index 0000000..67376a5
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/downward_inference_preferred_over_horizontal.dart.textual_outline.expect
@@ -0,0 +1,2 @@
+testProductOfNums(List<num> values) {}
+main() {}
diff --git a/pkg/front_end/testcases/inference_update_1/downward_inference_preferred_over_horizontal.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/inference_update_1/downward_inference_preferred_over_horizontal.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..9079d6c
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/downward_inference_preferred_over_horizontal.dart.textual_outline_modelled.expect
@@ -0,0 +1,2 @@
+main() {}
+testProductOfNums(List<num> values) {}
diff --git a/pkg/front_end/testcases/inference_update_1/downward_inference_preferred_over_horizontal.dart.weak.expect b/pkg/front_end/testcases/inference_update_1/downward_inference_preferred_over_horizontal.dart.weak.expect
new file mode 100644
index 0000000..e07090c
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/downward_inference_preferred_over_horizontal.dart.weak.expect
@@ -0,0 +1,8 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method testProductOfNums(core::List<core::num> values) → dynamic {
+  core::num a = values.{core::Iterable::fold}<core::num>(1, (core::num p, core::num v) → core::num => p.{core::num::*}(v){(core::num) → core::num}){(core::num, (core::num, core::num) → core::num) → core::num};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_update_1/downward_inference_preferred_over_horizontal.dart.weak.modular.expect b/pkg/front_end/testcases/inference_update_1/downward_inference_preferred_over_horizontal.dart.weak.modular.expect
new file mode 100644
index 0000000..e07090c
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/downward_inference_preferred_over_horizontal.dart.weak.modular.expect
@@ -0,0 +1,8 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method testProductOfNums(core::List<core::num> values) → dynamic {
+  core::num a = values.{core::Iterable::fold}<core::num>(1, (core::num p, core::num v) → core::num => p.{core::num::*}(v){(core::num) → core::num}){(core::num, (core::num, core::num) → core::num) → core::num};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_update_1/downward_inference_preferred_over_horizontal.dart.weak.outline.expect b/pkg/front_end/testcases/inference_update_1/downward_inference_preferred_over_horizontal.dart.weak.outline.expect
new file mode 100644
index 0000000..f885afa
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/downward_inference_preferred_over_horizontal.dart.weak.outline.expect
@@ -0,0 +1,8 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method testProductOfNums(core::List<core::num> values) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference_update_1/downward_inference_preferred_over_horizontal.dart.weak.transformed.expect b/pkg/front_end/testcases/inference_update_1/downward_inference_preferred_over_horizontal.dart.weak.transformed.expect
new file mode 100644
index 0000000..e07090c
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/downward_inference_preferred_over_horizontal.dart.weak.transformed.expect
@@ -0,0 +1,8 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method testProductOfNums(core::List<core::num> values) → dynamic {
+  core::num a = values.{core::Iterable::fold}<core::num>(1, (core::num p, core::num v) → core::num => p.{core::num::*}(v){(core::num) → core::num}){(core::num, (core::num, core::num) → core::num) → core::num};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_update_1/horizontal_inference_extension_method.dart b/pkg/front_end/testcases/inference_update_1/horizontal_inference_extension_method.dart
new file mode 100644
index 0000000..d6220a0
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/horizontal_inference_extension_method.dart
@@ -0,0 +1,173 @@
+// 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.
+
+// Tests that horizontal inference works properly when the invocation is an
+// extension member.  This is an important corner case because the front end
+// adds an implicit `this` argument to extension members as part of the lowering
+// process.  We need to make sure that the dependency tracking logic properly
+// accounts for this extra argument.
+
+// SharedOptions=--enable-experiment=inference-update-1
+
+testLaterUnnamedParameter(int i) {
+  i._laterUnnamedParameter(0, (x) {
+    x;
+  });
+}
+
+/// This special case verifies that the implementations correctly associate the
+/// zeroth positional parameter with the corresponding argument (even if that
+/// argument isn't in the zeroth position at the call site).
+testLaterUnnamedParameterDependsOnNamedParameter(int i) {
+  i._laterUnnamedParameterDependsOnNamedParameter(a: 0, (x) {
+    x;
+  });
+}
+
+testEarlierUnnamedParameter(int i) {
+  i._earlierUnnamedParameter((x) {
+    x;
+  }, 0);
+}
+
+testLaterNamedParameter(int i) {
+  i._laterNamedParameter(
+      a: 0,
+      b: (x) {
+        x;
+      });
+}
+
+testEarlierNamedParameter(int i) {
+  i._earlierNamedParameter(
+      a: (x) {
+        x;
+      },
+      b: 0);
+}
+
+/// This special case verifies that the implementations correctly associate the
+/// zeroth positional parameter with the corresponding argument (even if that
+/// argument isn't in the zeroth position at the call site).
+testEarlierNamedParameterDependsOnUnnamedParameter(int i) {
+  i._earlierNamedParameterDependsOnUnnamedParameter(a: (x) {
+    x;
+  }, 0);
+}
+
+testPropagateToReturnType(int i) {
+  i._propagateToReturnType(0, (x) => [x]);
+}
+
+// The test cases below exercise situations where there are multiple closures in
+// the invocation, and they need to be inferred in the right order.
+
+testClosureAsParameterType(int i) {
+  i._closureAsParameterType(() => 0, (h) => [h()])
+      ;
+}
+
+testPropagateToEarlierClosure(int i) {
+  i._propagateToEarlierClosure((x) => [x], () => 0)
+      ;
+}
+
+testPropagateToLaterClosure(int i) {
+  i._propagateToLaterClosure(() => 0, (x) => [x])
+      ;
+}
+
+testLongDependencyChain(int i) {
+  i._longDependencyChain(() => [0], (x) => x.single,
+          (y) => {y})
+      ;
+}
+
+testDependencyCycle(int i) {
+  i._dependencyCycle((x) => [x],
+          (y) => {y})
+      ;
+}
+
+testPropagateFromContravariantReturnType(int i) {
+  i._propagateFromContravariantReturnType(() => (int i) {}, (x) => [x])
+      ;
+}
+
+testPropagateToContravariantParameterType(int i) {
+  i._propagateToContravariantParameterType(() => 0, (x) => [x])
+      ;
+}
+
+testReturnTypeRefersToMultipleTypeVars(int i) {
+  i._returnTypeRefersToMultipleTypeVars(() => {0: ''}, (k) {
+    k;
+  }, (v) {
+    v;
+  });
+}
+
+testUnnecessaryDueToNoDependency(int i) {
+  i._unnecessaryDueToNoDependency(() => 0, null);
+}
+
+testUnnecessaryDueToExplicitParameterTypeNamed(int i) {
+  var a = i._unnecessaryDueToExplicitParameterTypeNamed(null, ({int? x, required y}) => (x ?? 0) + y);
+  a;
+}
+
+testParenthesized(int i) {
+  i._parenthesized(0, ((x) {
+    x;
+  }));
+}
+
+testParenthesizedNamed(int i) {
+  i._parenthesizedNamed(
+      a: 0,
+      b: ((x) {
+        x;
+      }));
+}
+
+testParenthesizedTwice(int i) {
+  i._parenthesizedTwice(0, (((x) {
+    x;
+  })));
+}
+
+testParenthesizedTwiceNamed(int i) {
+  i._parenthesizedTwiceNamed(
+      a: 0,
+      b: (((x) {
+        x;
+      })));
+}
+
+extension on int {
+  T _laterUnnamedParameter<T>(T x, void Function(T) y) => throw '';
+  void _laterUnnamedParameterDependsOnNamedParameter<T>(void Function(T) x, {required T a}) => throw '';
+  void _earlierUnnamedParameter<T>(void Function(T) x, T y) => throw '';
+  void _laterNamedParameter<T>({required T a, required void Function(T) b}) => throw '';
+  void _earlierNamedParameter<T>({required void Function(T) a, required T b}) => throw '';
+  void _earlierNamedParameterDependsOnUnnamedParameter<T>(T b, {required void Function(T) a}) => throw '';
+  U _propagateToReturnType<T, U>(T x, U Function(T) y) => throw '';
+  U _closureAsParameterType<T, U>(T x, U Function(T) y) => throw '';
+  U _propagateToEarlierClosure<T, U>(U Function(T) x, T Function() y) => throw '';
+  U _propagateToLaterClosure<T, U>(T Function() x, U Function(T) y) => throw '';
+  V _longDependencyChain<T, U, V>(T Function() x, U Function(T) y, V Function(U) z) => throw '';
+  Map<T, U> _dependencyCycle<T, U>(T Function(U) x, U Function(T) y) => throw '';
+  U _propagateFromContravariantReturnType<T, U>(void Function(T) Function() x, U Function(T) y) => throw '';
+  U _propagateToContravariantParameterType<T, U>(T Function() x, U Function(void Function(T)) y) => throw '';
+  void _returnTypeRefersToMultipleTypeVars<T, U>(
+            Map<T, U> Function() x, void Function(T) y, void Function(U) z) => throw '';
+  T _unnecessaryDueToNoDependency<T>(T Function() x, T y) => throw '';
+  T _unnecessaryDueToExplicitParameterTypeNamed<T>(T x, T Function({required T x, required int y}) y) => throw '';
+  void _parenthesized<T>(T x, void Function(T) y) => throw '';
+  void _parenthesizedNamed<T>({required T a, required void Function(T) b}) => throw '';
+  void _parenthesizedTwice<T>(T x, void Function(T) y) => throw '';
+  void _parenthesizedTwiceNamed<T>({required T a, required void Function(T) b}) => throw '';
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference_update_1/horizontal_inference_extension_method.dart.textual_outline.expect b/pkg/front_end/testcases/inference_update_1/horizontal_inference_extension_method.dart.textual_outline.expect
new file mode 100644
index 0000000..3732332
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/horizontal_inference_extension_method.dart.textual_outline.expect
@@ -0,0 +1,68 @@
+testLaterUnnamedParameter(int i) {}
+testLaterUnnamedParameterDependsOnNamedParameter(int i) {}
+testEarlierUnnamedParameter(int i) {}
+testLaterNamedParameter(int i) {}
+testEarlierNamedParameter(int i) {}
+testEarlierNamedParameterDependsOnUnnamedParameter(int i) {}
+testPropagateToReturnType(int i) {}
+testClosureAsParameterType(int i) {}
+testPropagateToEarlierClosure(int i) {}
+testPropagateToLaterClosure(int i) {}
+testLongDependencyChain(int i) {}
+testDependencyCycle(int i) {}
+testPropagateFromContravariantReturnType(int i) {}
+testPropagateToContravariantParameterType(int i) {}
+testReturnTypeRefersToMultipleTypeVars(int i) {}
+testUnnecessaryDueToNoDependency(int i) {}
+testUnnecessaryDueToExplicitParameterTypeNamed(int i) {}
+testParenthesized(int i) {}
+testParenthesizedNamed(int i) {}
+testParenthesizedTwice(int i) {}
+testParenthesizedTwiceNamed(int i) {}
+
+extension on int {
+  T _laterUnnamedParameter<T>(T x, void Function(T) y) => throw '';
+  void _laterUnnamedParameterDependsOnNamedParameter<T>(void Function(T) x,
+          {required T a}) =>
+      throw '';
+  void _earlierUnnamedParameter<T>(void Function(T) x, T y) => throw '';
+  void _laterNamedParameter<T>({required T a, required void Function(T) b}) =>
+      throw '';
+  void _earlierNamedParameter<T>({required void Function(T) a, required T b}) =>
+      throw '';
+  void _earlierNamedParameterDependsOnUnnamedParameter<T>(T b,
+          {required void Function(T) a}) =>
+      throw '';
+  U _propagateToReturnType<T, U>(T x, U Function(T) y) => throw '';
+  U _closureAsParameterType<T, U>(T x, U Function(T) y) => throw '';
+  U _propagateToEarlierClosure<T, U>(U Function(T) x, T Function() y) =>
+      throw '';
+  U _propagateToLaterClosure<T, U>(T Function() x, U Function(T) y) => throw '';
+  V _longDependencyChain<T, U, V>(
+          T Function() x, U Function(T) y, V Function(U) z) =>
+      throw '';
+  Map<T, U> _dependencyCycle<T, U>(T Function(U) x, U Function(T) y) =>
+      throw '';
+  U _propagateFromContravariantReturnType<T, U>(
+          void Function(T) Function() x, U Function(T) y) =>
+      throw '';
+  U _propagateToContravariantParameterType<T, U>(
+          T Function() x, U Function(void Function(T)) y) =>
+      throw '';
+  void _returnTypeRefersToMultipleTypeVars<T, U>(
+          Map<T, U> Function() x, void Function(T) y, void Function(U) z) =>
+      throw '';
+  T _unnecessaryDueToNoDependency<T>(T Function() x, T y) => throw '';
+  T _unnecessaryDueToExplicitParameterTypeNamed<T>(
+          T x, T Function({required T x, required int y}) y) =>
+      throw '';
+  void _parenthesized<T>(T x, void Function(T) y) => throw '';
+  void _parenthesizedNamed<T>({required T a, required void Function(T) b}) =>
+      throw '';
+  void _parenthesizedTwice<T>(T x, void Function(T) y) => throw '';
+  void _parenthesizedTwiceNamed<T>(
+          {required T a, required void Function(T) b}) =>
+      throw '';
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference_update_1/horizontal_inference_extension_method.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/inference_update_1/horizontal_inference_extension_method.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..5b33e9f
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/horizontal_inference_extension_method.dart.textual_outline_modelled.expect
@@ -0,0 +1,67 @@
+extension on int {
+  Map<T, U> _dependencyCycle<T, U>(T Function(U) x, U Function(T) y) =>
+      throw '';
+  T _laterUnnamedParameter<T>(T x, void Function(T) y) => throw '';
+  T _unnecessaryDueToExplicitParameterTypeNamed<T>(
+          T x, T Function({required T x, required int y}) y) =>
+      throw '';
+  T _unnecessaryDueToNoDependency<T>(T Function() x, T y) => throw '';
+  U _closureAsParameterType<T, U>(T x, U Function(T) y) => throw '';
+  U _propagateFromContravariantReturnType<T, U>(
+          void Function(T) Function() x, U Function(T) y) =>
+      throw '';
+  U _propagateToContravariantParameterType<T, U>(
+          T Function() x, U Function(void Function(T)) y) =>
+      throw '';
+  U _propagateToEarlierClosure<T, U>(U Function(T) x, T Function() y) =>
+      throw '';
+  U _propagateToLaterClosure<T, U>(T Function() x, U Function(T) y) => throw '';
+  U _propagateToReturnType<T, U>(T x, U Function(T) y) => throw '';
+  V _longDependencyChain<T, U, V>(
+          T Function() x, U Function(T) y, V Function(U) z) =>
+      throw '';
+  void _earlierNamedParameter<T>({required void Function(T) a, required T b}) =>
+      throw '';
+  void _earlierNamedParameterDependsOnUnnamedParameter<T>(T b,
+          {required void Function(T) a}) =>
+      throw '';
+  void _earlierUnnamedParameter<T>(void Function(T) x, T y) => throw '';
+  void _laterNamedParameter<T>({required T a, required void Function(T) b}) =>
+      throw '';
+  void _laterUnnamedParameterDependsOnNamedParameter<T>(void Function(T) x,
+          {required T a}) =>
+      throw '';
+  void _parenthesized<T>(T x, void Function(T) y) => throw '';
+  void _parenthesizedNamed<T>({required T a, required void Function(T) b}) =>
+      throw '';
+  void _parenthesizedTwice<T>(T x, void Function(T) y) => throw '';
+  void _parenthesizedTwiceNamed<T>(
+          {required T a, required void Function(T) b}) =>
+      throw '';
+  void _returnTypeRefersToMultipleTypeVars<T, U>(
+          Map<T, U> Function() x, void Function(T) y, void Function(U) z) =>
+      throw '';
+}
+
+main() {}
+testClosureAsParameterType(int i) {}
+testDependencyCycle(int i) {}
+testEarlierNamedParameter(int i) {}
+testEarlierNamedParameterDependsOnUnnamedParameter(int i) {}
+testEarlierUnnamedParameter(int i) {}
+testLaterNamedParameter(int i) {}
+testLaterUnnamedParameter(int i) {}
+testLaterUnnamedParameterDependsOnNamedParameter(int i) {}
+testLongDependencyChain(int i) {}
+testParenthesized(int i) {}
+testParenthesizedNamed(int i) {}
+testParenthesizedTwice(int i) {}
+testParenthesizedTwiceNamed(int i) {}
+testPropagateFromContravariantReturnType(int i) {}
+testPropagateToContravariantParameterType(int i) {}
+testPropagateToEarlierClosure(int i) {}
+testPropagateToLaterClosure(int i) {}
+testPropagateToReturnType(int i) {}
+testReturnTypeRefersToMultipleTypeVars(int i) {}
+testUnnecessaryDueToExplicitParameterTypeNamed(int i) {}
+testUnnecessaryDueToNoDependency(int i) {}
diff --git a/pkg/front_end/testcases/inference_update_1/horizontal_inference_extension_method.dart.weak.expect b/pkg/front_end/testcases/inference_update_1/horizontal_inference_extension_method.dart.weak.expect
new file mode 100644
index 0000000..e09a14c
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/horizontal_inference_extension_method.dart.weak.expect
@@ -0,0 +1,232 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+extension _extension#0 on core::int {
+  method _laterUnnamedParameter = self::_extension#0|_laterUnnamedParameter;
+  tearoff _laterUnnamedParameter = self::_extension#0|get#_laterUnnamedParameter;
+  method _laterUnnamedParameterDependsOnNamedParameter = self::_extension#0|_laterUnnamedParameterDependsOnNamedParameter;
+  tearoff _laterUnnamedParameterDependsOnNamedParameter = self::_extension#0|get#_laterUnnamedParameterDependsOnNamedParameter;
+  method _earlierUnnamedParameter = self::_extension#0|_earlierUnnamedParameter;
+  tearoff _earlierUnnamedParameter = self::_extension#0|get#_earlierUnnamedParameter;
+  method _laterNamedParameter = self::_extension#0|_laterNamedParameter;
+  tearoff _laterNamedParameter = self::_extension#0|get#_laterNamedParameter;
+  method _earlierNamedParameter = self::_extension#0|_earlierNamedParameter;
+  tearoff _earlierNamedParameter = self::_extension#0|get#_earlierNamedParameter;
+  method _earlierNamedParameterDependsOnUnnamedParameter = self::_extension#0|_earlierNamedParameterDependsOnUnnamedParameter;
+  tearoff _earlierNamedParameterDependsOnUnnamedParameter = self::_extension#0|get#_earlierNamedParameterDependsOnUnnamedParameter;
+  method _propagateToReturnType = self::_extension#0|_propagateToReturnType;
+  tearoff _propagateToReturnType = self::_extension#0|get#_propagateToReturnType;
+  method _closureAsParameterType = self::_extension#0|_closureAsParameterType;
+  tearoff _closureAsParameterType = self::_extension#0|get#_closureAsParameterType;
+  method _propagateToEarlierClosure = self::_extension#0|_propagateToEarlierClosure;
+  tearoff _propagateToEarlierClosure = self::_extension#0|get#_propagateToEarlierClosure;
+  method _propagateToLaterClosure = self::_extension#0|_propagateToLaterClosure;
+  tearoff _propagateToLaterClosure = self::_extension#0|get#_propagateToLaterClosure;
+  method _longDependencyChain = self::_extension#0|_longDependencyChain;
+  tearoff _longDependencyChain = self::_extension#0|get#_longDependencyChain;
+  method _dependencyCycle = self::_extension#0|_dependencyCycle;
+  tearoff _dependencyCycle = self::_extension#0|get#_dependencyCycle;
+  method _propagateFromContravariantReturnType = self::_extension#0|_propagateFromContravariantReturnType;
+  tearoff _propagateFromContravariantReturnType = self::_extension#0|get#_propagateFromContravariantReturnType;
+  method _propagateToContravariantParameterType = self::_extension#0|_propagateToContravariantParameterType;
+  tearoff _propagateToContravariantParameterType = self::_extension#0|get#_propagateToContravariantParameterType;
+  method _returnTypeRefersToMultipleTypeVars = self::_extension#0|_returnTypeRefersToMultipleTypeVars;
+  tearoff _returnTypeRefersToMultipleTypeVars = self::_extension#0|get#_returnTypeRefersToMultipleTypeVars;
+  method _unnecessaryDueToNoDependency = self::_extension#0|_unnecessaryDueToNoDependency;
+  tearoff _unnecessaryDueToNoDependency = self::_extension#0|get#_unnecessaryDueToNoDependency;
+  method _unnecessaryDueToExplicitParameterTypeNamed = self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed;
+  tearoff _unnecessaryDueToExplicitParameterTypeNamed = self::_extension#0|get#_unnecessaryDueToExplicitParameterTypeNamed;
+  method _parenthesized = self::_extension#0|_parenthesized;
+  tearoff _parenthesized = self::_extension#0|get#_parenthesized;
+  method _parenthesizedNamed = self::_extension#0|_parenthesizedNamed;
+  tearoff _parenthesizedNamed = self::_extension#0|get#_parenthesizedNamed;
+  method _parenthesizedTwice = self::_extension#0|_parenthesizedTwice;
+  tearoff _parenthesizedTwice = self::_extension#0|get#_parenthesizedTwice;
+  method _parenthesizedTwiceNamed = self::_extension#0|_parenthesizedTwiceNamed;
+  tearoff _parenthesizedTwiceNamed = self::_extension#0|get#_parenthesizedTwiceNamed;
+}
+static method testLaterUnnamedParameter(core::int i) → dynamic {
+  self::_extension#0|_laterUnnamedParameter<core::int>(i, 0, (core::int x) → void {
+    x;
+  });
+}
+static method testLaterUnnamedParameterDependsOnNamedParameter(core::int i) → dynamic {
+  self::_extension#0|_laterUnnamedParameterDependsOnNamedParameter<core::int>(i, (core::int x) → void {
+    x;
+  }, a: 0);
+}
+static method testEarlierUnnamedParameter(core::int i) → dynamic {
+  self::_extension#0|_earlierUnnamedParameter<core::int>(i, (core::int x) → void {
+    x;
+  }, 0);
+}
+static method testLaterNamedParameter(core::int i) → dynamic {
+  self::_extension#0|_laterNamedParameter<core::int>(i, a: 0, b: (core::int x) → void {
+    x;
+  });
+}
+static method testEarlierNamedParameter(core::int i) → dynamic {
+  self::_extension#0|_earlierNamedParameter<core::int>(i, a: (core::int x) → void {
+    x;
+  }, b: 0);
+}
+static method testEarlierNamedParameterDependsOnUnnamedParameter(core::int i) → dynamic {
+  self::_extension#0|_earlierNamedParameterDependsOnUnnamedParameter<core::int>(i, 0, a: (core::int x) → void {
+    x;
+  });
+}
+static method testPropagateToReturnType(core::int i) → dynamic {
+  self::_extension#0|_propagateToReturnType<core::int, core::List<core::int>>(i, 0, (core::int x) → core::List<core::int> => <core::int>[x]);
+}
+static method testClosureAsParameterType(core::int i) → dynamic {
+  self::_extension#0|_closureAsParameterType<() → core::int, core::List<core::int>>(i, () → core::int => 0, (() → core::int h) → core::List<core::int> => <core::int>[h(){() → core::int}]);
+}
+static method testPropagateToEarlierClosure(core::int i) → dynamic {
+  self::_extension#0|_propagateToEarlierClosure<core::int, core::List<core::int>>(i, (core::int x) → core::List<core::int> => <core::int>[x], () → core::int => 0);
+}
+static method testPropagateToLaterClosure(core::int i) → dynamic {
+  self::_extension#0|_propagateToLaterClosure<core::int, core::List<core::int>>(i, () → core::int => 0, (core::int x) → core::List<core::int> => <core::int>[x]);
+}
+static method testLongDependencyChain(core::int i) → dynamic {
+  self::_extension#0|_longDependencyChain<core::List<core::int>, core::int, core::Set<core::int>>(i, () → core::List<core::int> => <core::int>[0], (core::List<core::int> x) → core::int => x.{core::Iterable::single}{core::int}, (core::int y) → core::Set<core::int> => block {
+    final core::Set<core::int> #t1 = col::LinkedHashSet::•<core::int>();
+    #t1.{core::Set::add}{Invariant}(y){(core::int) → core::bool};
+  } =>#t1);
+}
+static method testDependencyCycle(core::int i) → dynamic {
+  self::_extension#0|_dependencyCycle<core::List<core::Object?>, core::Set<core::Object?>>(i, (core::Object? x) → core::List<core::Object?> => <core::Object?>[x], (core::Object? y) → core::Set<core::Object?> => block {
+    final core::Set<core::Object?> #t2 = col::LinkedHashSet::•<core::Object?>();
+    #t2.{core::Set::add}{Invariant}(y){(core::Object?) → core::bool};
+  } =>#t2);
+}
+static method testPropagateFromContravariantReturnType(core::int i) → dynamic {
+  self::_extension#0|_propagateFromContravariantReturnType<core::int, core::List<core::int>>(i, () → (core::int) → void => (core::int i) → void {}, (core::int x) → core::List<core::int> => <core::int>[x]);
+}
+static method testPropagateToContravariantParameterType(core::int i) → dynamic {
+  self::_extension#0|_propagateToContravariantParameterType<core::int, core::List<(core::int) → void>>(i, () → core::int => 0, ((core::int) → void x) → core::List<(core::int) → void> => <(core::int) → void>[x]);
+}
+static method testReturnTypeRefersToMultipleTypeVars(core::int i) → dynamic {
+  self::_extension#0|_returnTypeRefersToMultipleTypeVars<core::int, core::String>(i, () → core::Map<core::int, core::String> => <core::int, core::String>{0: ""}, (core::int k) → void {
+    k;
+  }, (core::String v) → void {
+    v;
+  });
+}
+static method testUnnecessaryDueToNoDependency(core::int i) → dynamic {
+  self::_extension#0|_unnecessaryDueToNoDependency<core::int?>(i, () → core::int => 0, null);
+}
+static method testUnnecessaryDueToExplicitParameterTypeNamed(core::int i) → dynamic {
+  core::int? a = self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed<core::int?>(i, null, ({core::int? x = #C1, required core::int y = #C1}) → core::int => (let final core::int? #t3 = x in #t3 == null ?{core::int} 0 : #t3{core::int}).{core::num::+}(y){(core::num) → core::int});
+  a;
+}
+static method testParenthesized(core::int i) → dynamic {
+  self::_extension#0|_parenthesized<core::int>(i, 0, (core::int x) → void {
+    x;
+  });
+}
+static method testParenthesizedNamed(core::int i) → dynamic {
+  self::_extension#0|_parenthesizedNamed<core::int>(i, a: 0, b: (core::int x) → void {
+    x;
+  });
+}
+static method testParenthesizedTwice(core::int i) → dynamic {
+  self::_extension#0|_parenthesizedTwice<core::int>(i, 0, (core::int x) → void {
+    x;
+  });
+}
+static method testParenthesizedTwiceNamed(core::int i) → dynamic {
+  self::_extension#0|_parenthesizedTwiceNamed<core::int>(i, a: 0, b: (core::int x) → void {
+    x;
+  });
+}
+static method _extension#0|_laterUnnamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_laterUnnamedParameter::T% x, (self::_extension#0|_laterUnnamedParameter::T%) → void y) → self::_extension#0|_laterUnnamedParameter::T%
+  return throw "";
+static method _extension#0|get#_laterUnnamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>(T%, (T%) → void) → T%
+  return <T extends core::Object? = dynamic>(T% x, (T%) → void y) → T% => self::_extension#0|_laterUnnamedParameter<T%>(#this, x, y);
+static method _extension#0|_laterUnnamedParameterDependsOnNamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, (self::_extension#0|_laterUnnamedParameterDependsOnNamedParameter::T%) → void x, {required self::_extension#0|_laterUnnamedParameterDependsOnNamedParameter::T% a = #C1}) → void
+  return throw "";
+static method _extension#0|get#_laterUnnamedParameterDependsOnNamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>((T%) → void, {a: T%}) → void
+  return <T extends core::Object? = dynamic>((T%) → void x, {T% a = #C1}) → void => self::_extension#0|_laterUnnamedParameterDependsOnNamedParameter<T%>(#this, x, a: a);
+static method _extension#0|_earlierUnnamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, (self::_extension#0|_earlierUnnamedParameter::T%) → void x, self::_extension#0|_earlierUnnamedParameter::T% y) → void
+  return throw "";
+static method _extension#0|get#_earlierUnnamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>((T%) → void, T%) → void
+  return <T extends core::Object? = dynamic>((T%) → void x, T% y) → void => self::_extension#0|_earlierUnnamedParameter<T%>(#this, x, y);
+static method _extension#0|_laterNamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, {required self::_extension#0|_laterNamedParameter::T% a = #C1, required (self::_extension#0|_laterNamedParameter::T%) → void b = #C1}) → void
+  return throw "";
+static method _extension#0|get#_laterNamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>({a: T%, b: (T%) → void}) → void
+  return <T extends core::Object? = dynamic>({T% a = #C1, (T%) → void b = #C1}) → void => self::_extension#0|_laterNamedParameter<T%>(#this, a: a, b: b);
+static method _extension#0|_earlierNamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, {required (self::_extension#0|_earlierNamedParameter::T%) → void a = #C1, required self::_extension#0|_earlierNamedParameter::T% b = #C1}) → void
+  return throw "";
+static method _extension#0|get#_earlierNamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>({a: (T%) → void, b: T%}) → void
+  return <T extends core::Object? = dynamic>({(T%) → void a = #C1, T% b = #C1}) → void => self::_extension#0|_earlierNamedParameter<T%>(#this, a: a, b: b);
+static method _extension#0|_earlierNamedParameterDependsOnUnnamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_earlierNamedParameterDependsOnUnnamedParameter::T% b, {required (self::_extension#0|_earlierNamedParameterDependsOnUnnamedParameter::T%) → void a = #C1}) → void
+  return throw "";
+static method _extension#0|get#_earlierNamedParameterDependsOnUnnamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>(T%, {a: (T%) → void}) → void
+  return <T extends core::Object? = dynamic>(T% b, {(T%) → void a = #C1}) → void => self::_extension#0|_earlierNamedParameterDependsOnUnnamedParameter<T%>(#this, b, a: a);
+static method _extension#0|_propagateToReturnType<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_propagateToReturnType::T% x, (self::_extension#0|_propagateToReturnType::T%) → self::_extension#0|_propagateToReturnType::U% y) → self::_extension#0|_propagateToReturnType::U%
+  return throw "";
+static method _extension#0|get#_propagateToReturnType(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(T%, (T%) → U%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(T% x, (T%) → U% y) → U% => self::_extension#0|_propagateToReturnType<T%, U%>(#this, x, y);
+static method _extension#0|_closureAsParameterType<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_closureAsParameterType::T% x, (self::_extension#0|_closureAsParameterType::T%) → self::_extension#0|_closureAsParameterType::U% y) → self::_extension#0|_closureAsParameterType::U%
+  return throw "";
+static method _extension#0|get#_closureAsParameterType(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(T%, (T%) → U%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(T% x, (T%) → U% y) → U% => self::_extension#0|_closureAsParameterType<T%, U%>(#this, x, y);
+static method _extension#0|_propagateToEarlierClosure<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, (self::_extension#0|_propagateToEarlierClosure::T%) → self::_extension#0|_propagateToEarlierClosure::U% x, () → self::_extension#0|_propagateToEarlierClosure::T% y) → self::_extension#0|_propagateToEarlierClosure::U%
+  return throw "";
+static method _extension#0|get#_propagateToEarlierClosure(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>((T%) → U%, () → T%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>((T%) → U% x, () → T% y) → U% => self::_extension#0|_propagateToEarlierClosure<T%, U%>(#this, x, y);
+static method _extension#0|_propagateToLaterClosure<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, () → self::_extension#0|_propagateToLaterClosure::T% x, (self::_extension#0|_propagateToLaterClosure::T%) → self::_extension#0|_propagateToLaterClosure::U% y) → self::_extension#0|_propagateToLaterClosure::U%
+  return throw "";
+static method _extension#0|get#_propagateToLaterClosure(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → T%, (T%) → U%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → T% x, (T%) → U% y) → U% => self::_extension#0|_propagateToLaterClosure<T%, U%>(#this, x, y);
+static method _extension#0|get#_longDependencyChain(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic, V extends core::Object? = dynamic>(() → T%, (T%) → U%, (U%) → V%) → V%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic, V extends core::Object? = dynamic>(() → T% x, (T%) → U% y, (U%) → V% z) → V% => self::_extension#0|_longDependencyChain<T%, U%, V%>(#this, x, y, z);
+static method _extension#0|_longDependencyChain<T extends core::Object? = dynamic, U extends core::Object? = dynamic, V extends core::Object? = dynamic>(lowered final core::int #this, () → self::_extension#0|_longDependencyChain::T% x, (self::_extension#0|_longDependencyChain::T%) → self::_extension#0|_longDependencyChain::U% y, (self::_extension#0|_longDependencyChain::U%) → self::_extension#0|_longDependencyChain::V% z) → self::_extension#0|_longDependencyChain::V%
+  return throw "";
+static method _extension#0|_dependencyCycle<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, (self::_extension#0|_dependencyCycle::U%) → self::_extension#0|_dependencyCycle::T% x, (self::_extension#0|_dependencyCycle::T%) → self::_extension#0|_dependencyCycle::U% y) → core::Map<self::_extension#0|_dependencyCycle::T%, self::_extension#0|_dependencyCycle::U%>
+  return throw "";
+static method _extension#0|get#_dependencyCycle(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>((U%) → T%, (T%) → U%) → core::Map<T%, U%>
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>((U%) → T% x, (T%) → U% y) → core::Map<T%, U%> => self::_extension#0|_dependencyCycle<T%, U%>(#this, x, y);
+static method _extension#0|_propagateFromContravariantReturnType<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, () → (self::_extension#0|_propagateFromContravariantReturnType::T%) → void x, (self::_extension#0|_propagateFromContravariantReturnType::T%) → self::_extension#0|_propagateFromContravariantReturnType::U% y) → self::_extension#0|_propagateFromContravariantReturnType::U%
+  return throw "";
+static method _extension#0|get#_propagateFromContravariantReturnType(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → (T%) → void, (T%) → U%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → (T%) → void x, (T%) → U% y) → U% => self::_extension#0|_propagateFromContravariantReturnType<T%, U%>(#this, x, y);
+static method _extension#0|_propagateToContravariantParameterType<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, () → self::_extension#0|_propagateToContravariantParameterType::T% x, ((self::_extension#0|_propagateToContravariantParameterType::T%) → void) → self::_extension#0|_propagateToContravariantParameterType::U% y) → self::_extension#0|_propagateToContravariantParameterType::U%
+  return throw "";
+static method _extension#0|get#_propagateToContravariantParameterType(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → T%, ((T%) → void) → U%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → T% x, ((T%) → void) → U% y) → U% => self::_extension#0|_propagateToContravariantParameterType<T%, U%>(#this, x, y);
+static method _extension#0|_returnTypeRefersToMultipleTypeVars<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, () → core::Map<self::_extension#0|_returnTypeRefersToMultipleTypeVars::T%, self::_extension#0|_returnTypeRefersToMultipleTypeVars::U%> x, (self::_extension#0|_returnTypeRefersToMultipleTypeVars::T%) → void y, (self::_extension#0|_returnTypeRefersToMultipleTypeVars::U%) → void z) → void
+  return throw "";
+static method _extension#0|get#_returnTypeRefersToMultipleTypeVars(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → core::Map<T%, U%>, (T%) → void, (U%) → void) → void
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → core::Map<T%, U%> x, (T%) → void y, (U%) → void z) → void => self::_extension#0|_returnTypeRefersToMultipleTypeVars<T%, U%>(#this, x, y, z);
+static method _extension#0|_unnecessaryDueToNoDependency<T extends core::Object? = dynamic>(lowered final core::int #this, () → self::_extension#0|_unnecessaryDueToNoDependency::T% x, self::_extension#0|_unnecessaryDueToNoDependency::T% y) → self::_extension#0|_unnecessaryDueToNoDependency::T%
+  return throw "";
+static method _extension#0|get#_unnecessaryDueToNoDependency(lowered final core::int #this) → <T extends core::Object? = dynamic>(() → T%, T%) → T%
+  return <T extends core::Object? = dynamic>(() → T% x, T% y) → T% => self::_extension#0|_unnecessaryDueToNoDependency<T%>(#this, x, y);
+static method _extension#0|_unnecessaryDueToExplicitParameterTypeNamed<T extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed::T% x, ({required x: self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed::T%, required y: core::int}) → self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed::T% y) → self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed::T%
+  return throw "";
+static method _extension#0|get#_unnecessaryDueToExplicitParameterTypeNamed(lowered final core::int #this) → <T extends core::Object? = dynamic>(T%, ({required x: T%, required y: core::int}) → T%) → T%
+  return <T extends core::Object? = dynamic>(T% x, ({required x: T%, required y: core::int}) → T% y) → T% => self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed<T%>(#this, x, y);
+static method _extension#0|_parenthesized<T extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_parenthesized::T% x, (self::_extension#0|_parenthesized::T%) → void y) → void
+  return throw "";
+static method _extension#0|get#_parenthesized(lowered final core::int #this) → <T extends core::Object? = dynamic>(T%, (T%) → void) → void
+  return <T extends core::Object? = dynamic>(T% x, (T%) → void y) → void => self::_extension#0|_parenthesized<T%>(#this, x, y);
+static method _extension#0|_parenthesizedNamed<T extends core::Object? = dynamic>(lowered final core::int #this, {required self::_extension#0|_parenthesizedNamed::T% a = #C1, required (self::_extension#0|_parenthesizedNamed::T%) → void b = #C1}) → void
+  return throw "";
+static method _extension#0|get#_parenthesizedNamed(lowered final core::int #this) → <T extends core::Object? = dynamic>({a: T%, b: (T%) → void}) → void
+  return <T extends core::Object? = dynamic>({T% a = #C1, (T%) → void b = #C1}) → void => self::_extension#0|_parenthesizedNamed<T%>(#this, a: a, b: b);
+static method _extension#0|_parenthesizedTwice<T extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_parenthesizedTwice::T% x, (self::_extension#0|_parenthesizedTwice::T%) → void y) → void
+  return throw "";
+static method _extension#0|get#_parenthesizedTwice(lowered final core::int #this) → <T extends core::Object? = dynamic>(T%, (T%) → void) → void
+  return <T extends core::Object? = dynamic>(T% x, (T%) → void y) → void => self::_extension#0|_parenthesizedTwice<T%>(#this, x, y);
+static method _extension#0|_parenthesizedTwiceNamed<T extends core::Object? = dynamic>(lowered final core::int #this, {required self::_extension#0|_parenthesizedTwiceNamed::T% a = #C1, required (self::_extension#0|_parenthesizedTwiceNamed::T%) → void b = #C1}) → void
+  return throw "";
+static method _extension#0|get#_parenthesizedTwiceNamed(lowered final core::int #this) → <T extends core::Object? = dynamic>({a: T%, b: (T%) → void}) → void
+  return <T extends core::Object? = dynamic>({T% a = #C1, (T%) → void b = #C1}) → void => self::_extension#0|_parenthesizedTwiceNamed<T%>(#this, a: a, b: b);
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/inference_update_1/horizontal_inference_extension_method.dart.weak.modular.expect b/pkg/front_end/testcases/inference_update_1/horizontal_inference_extension_method.dart.weak.modular.expect
new file mode 100644
index 0000000..e09a14c
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/horizontal_inference_extension_method.dart.weak.modular.expect
@@ -0,0 +1,232 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+extension _extension#0 on core::int {
+  method _laterUnnamedParameter = self::_extension#0|_laterUnnamedParameter;
+  tearoff _laterUnnamedParameter = self::_extension#0|get#_laterUnnamedParameter;
+  method _laterUnnamedParameterDependsOnNamedParameter = self::_extension#0|_laterUnnamedParameterDependsOnNamedParameter;
+  tearoff _laterUnnamedParameterDependsOnNamedParameter = self::_extension#0|get#_laterUnnamedParameterDependsOnNamedParameter;
+  method _earlierUnnamedParameter = self::_extension#0|_earlierUnnamedParameter;
+  tearoff _earlierUnnamedParameter = self::_extension#0|get#_earlierUnnamedParameter;
+  method _laterNamedParameter = self::_extension#0|_laterNamedParameter;
+  tearoff _laterNamedParameter = self::_extension#0|get#_laterNamedParameter;
+  method _earlierNamedParameter = self::_extension#0|_earlierNamedParameter;
+  tearoff _earlierNamedParameter = self::_extension#0|get#_earlierNamedParameter;
+  method _earlierNamedParameterDependsOnUnnamedParameter = self::_extension#0|_earlierNamedParameterDependsOnUnnamedParameter;
+  tearoff _earlierNamedParameterDependsOnUnnamedParameter = self::_extension#0|get#_earlierNamedParameterDependsOnUnnamedParameter;
+  method _propagateToReturnType = self::_extension#0|_propagateToReturnType;
+  tearoff _propagateToReturnType = self::_extension#0|get#_propagateToReturnType;
+  method _closureAsParameterType = self::_extension#0|_closureAsParameterType;
+  tearoff _closureAsParameterType = self::_extension#0|get#_closureAsParameterType;
+  method _propagateToEarlierClosure = self::_extension#0|_propagateToEarlierClosure;
+  tearoff _propagateToEarlierClosure = self::_extension#0|get#_propagateToEarlierClosure;
+  method _propagateToLaterClosure = self::_extension#0|_propagateToLaterClosure;
+  tearoff _propagateToLaterClosure = self::_extension#0|get#_propagateToLaterClosure;
+  method _longDependencyChain = self::_extension#0|_longDependencyChain;
+  tearoff _longDependencyChain = self::_extension#0|get#_longDependencyChain;
+  method _dependencyCycle = self::_extension#0|_dependencyCycle;
+  tearoff _dependencyCycle = self::_extension#0|get#_dependencyCycle;
+  method _propagateFromContravariantReturnType = self::_extension#0|_propagateFromContravariantReturnType;
+  tearoff _propagateFromContravariantReturnType = self::_extension#0|get#_propagateFromContravariantReturnType;
+  method _propagateToContravariantParameterType = self::_extension#0|_propagateToContravariantParameterType;
+  tearoff _propagateToContravariantParameterType = self::_extension#0|get#_propagateToContravariantParameterType;
+  method _returnTypeRefersToMultipleTypeVars = self::_extension#0|_returnTypeRefersToMultipleTypeVars;
+  tearoff _returnTypeRefersToMultipleTypeVars = self::_extension#0|get#_returnTypeRefersToMultipleTypeVars;
+  method _unnecessaryDueToNoDependency = self::_extension#0|_unnecessaryDueToNoDependency;
+  tearoff _unnecessaryDueToNoDependency = self::_extension#0|get#_unnecessaryDueToNoDependency;
+  method _unnecessaryDueToExplicitParameterTypeNamed = self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed;
+  tearoff _unnecessaryDueToExplicitParameterTypeNamed = self::_extension#0|get#_unnecessaryDueToExplicitParameterTypeNamed;
+  method _parenthesized = self::_extension#0|_parenthesized;
+  tearoff _parenthesized = self::_extension#0|get#_parenthesized;
+  method _parenthesizedNamed = self::_extension#0|_parenthesizedNamed;
+  tearoff _parenthesizedNamed = self::_extension#0|get#_parenthesizedNamed;
+  method _parenthesizedTwice = self::_extension#0|_parenthesizedTwice;
+  tearoff _parenthesizedTwice = self::_extension#0|get#_parenthesizedTwice;
+  method _parenthesizedTwiceNamed = self::_extension#0|_parenthesizedTwiceNamed;
+  tearoff _parenthesizedTwiceNamed = self::_extension#0|get#_parenthesizedTwiceNamed;
+}
+static method testLaterUnnamedParameter(core::int i) → dynamic {
+  self::_extension#0|_laterUnnamedParameter<core::int>(i, 0, (core::int x) → void {
+    x;
+  });
+}
+static method testLaterUnnamedParameterDependsOnNamedParameter(core::int i) → dynamic {
+  self::_extension#0|_laterUnnamedParameterDependsOnNamedParameter<core::int>(i, (core::int x) → void {
+    x;
+  }, a: 0);
+}
+static method testEarlierUnnamedParameter(core::int i) → dynamic {
+  self::_extension#0|_earlierUnnamedParameter<core::int>(i, (core::int x) → void {
+    x;
+  }, 0);
+}
+static method testLaterNamedParameter(core::int i) → dynamic {
+  self::_extension#0|_laterNamedParameter<core::int>(i, a: 0, b: (core::int x) → void {
+    x;
+  });
+}
+static method testEarlierNamedParameter(core::int i) → dynamic {
+  self::_extension#0|_earlierNamedParameter<core::int>(i, a: (core::int x) → void {
+    x;
+  }, b: 0);
+}
+static method testEarlierNamedParameterDependsOnUnnamedParameter(core::int i) → dynamic {
+  self::_extension#0|_earlierNamedParameterDependsOnUnnamedParameter<core::int>(i, 0, a: (core::int x) → void {
+    x;
+  });
+}
+static method testPropagateToReturnType(core::int i) → dynamic {
+  self::_extension#0|_propagateToReturnType<core::int, core::List<core::int>>(i, 0, (core::int x) → core::List<core::int> => <core::int>[x]);
+}
+static method testClosureAsParameterType(core::int i) → dynamic {
+  self::_extension#0|_closureAsParameterType<() → core::int, core::List<core::int>>(i, () → core::int => 0, (() → core::int h) → core::List<core::int> => <core::int>[h(){() → core::int}]);
+}
+static method testPropagateToEarlierClosure(core::int i) → dynamic {
+  self::_extension#0|_propagateToEarlierClosure<core::int, core::List<core::int>>(i, (core::int x) → core::List<core::int> => <core::int>[x], () → core::int => 0);
+}
+static method testPropagateToLaterClosure(core::int i) → dynamic {
+  self::_extension#0|_propagateToLaterClosure<core::int, core::List<core::int>>(i, () → core::int => 0, (core::int x) → core::List<core::int> => <core::int>[x]);
+}
+static method testLongDependencyChain(core::int i) → dynamic {
+  self::_extension#0|_longDependencyChain<core::List<core::int>, core::int, core::Set<core::int>>(i, () → core::List<core::int> => <core::int>[0], (core::List<core::int> x) → core::int => x.{core::Iterable::single}{core::int}, (core::int y) → core::Set<core::int> => block {
+    final core::Set<core::int> #t1 = col::LinkedHashSet::•<core::int>();
+    #t1.{core::Set::add}{Invariant}(y){(core::int) → core::bool};
+  } =>#t1);
+}
+static method testDependencyCycle(core::int i) → dynamic {
+  self::_extension#0|_dependencyCycle<core::List<core::Object?>, core::Set<core::Object?>>(i, (core::Object? x) → core::List<core::Object?> => <core::Object?>[x], (core::Object? y) → core::Set<core::Object?> => block {
+    final core::Set<core::Object?> #t2 = col::LinkedHashSet::•<core::Object?>();
+    #t2.{core::Set::add}{Invariant}(y){(core::Object?) → core::bool};
+  } =>#t2);
+}
+static method testPropagateFromContravariantReturnType(core::int i) → dynamic {
+  self::_extension#0|_propagateFromContravariantReturnType<core::int, core::List<core::int>>(i, () → (core::int) → void => (core::int i) → void {}, (core::int x) → core::List<core::int> => <core::int>[x]);
+}
+static method testPropagateToContravariantParameterType(core::int i) → dynamic {
+  self::_extension#0|_propagateToContravariantParameterType<core::int, core::List<(core::int) → void>>(i, () → core::int => 0, ((core::int) → void x) → core::List<(core::int) → void> => <(core::int) → void>[x]);
+}
+static method testReturnTypeRefersToMultipleTypeVars(core::int i) → dynamic {
+  self::_extension#0|_returnTypeRefersToMultipleTypeVars<core::int, core::String>(i, () → core::Map<core::int, core::String> => <core::int, core::String>{0: ""}, (core::int k) → void {
+    k;
+  }, (core::String v) → void {
+    v;
+  });
+}
+static method testUnnecessaryDueToNoDependency(core::int i) → dynamic {
+  self::_extension#0|_unnecessaryDueToNoDependency<core::int?>(i, () → core::int => 0, null);
+}
+static method testUnnecessaryDueToExplicitParameterTypeNamed(core::int i) → dynamic {
+  core::int? a = self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed<core::int?>(i, null, ({core::int? x = #C1, required core::int y = #C1}) → core::int => (let final core::int? #t3 = x in #t3 == null ?{core::int} 0 : #t3{core::int}).{core::num::+}(y){(core::num) → core::int});
+  a;
+}
+static method testParenthesized(core::int i) → dynamic {
+  self::_extension#0|_parenthesized<core::int>(i, 0, (core::int x) → void {
+    x;
+  });
+}
+static method testParenthesizedNamed(core::int i) → dynamic {
+  self::_extension#0|_parenthesizedNamed<core::int>(i, a: 0, b: (core::int x) → void {
+    x;
+  });
+}
+static method testParenthesizedTwice(core::int i) → dynamic {
+  self::_extension#0|_parenthesizedTwice<core::int>(i, 0, (core::int x) → void {
+    x;
+  });
+}
+static method testParenthesizedTwiceNamed(core::int i) → dynamic {
+  self::_extension#0|_parenthesizedTwiceNamed<core::int>(i, a: 0, b: (core::int x) → void {
+    x;
+  });
+}
+static method _extension#0|_laterUnnamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_laterUnnamedParameter::T% x, (self::_extension#0|_laterUnnamedParameter::T%) → void y) → self::_extension#0|_laterUnnamedParameter::T%
+  return throw "";
+static method _extension#0|get#_laterUnnamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>(T%, (T%) → void) → T%
+  return <T extends core::Object? = dynamic>(T% x, (T%) → void y) → T% => self::_extension#0|_laterUnnamedParameter<T%>(#this, x, y);
+static method _extension#0|_laterUnnamedParameterDependsOnNamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, (self::_extension#0|_laterUnnamedParameterDependsOnNamedParameter::T%) → void x, {required self::_extension#0|_laterUnnamedParameterDependsOnNamedParameter::T% a = #C1}) → void
+  return throw "";
+static method _extension#0|get#_laterUnnamedParameterDependsOnNamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>((T%) → void, {a: T%}) → void
+  return <T extends core::Object? = dynamic>((T%) → void x, {T% a = #C1}) → void => self::_extension#0|_laterUnnamedParameterDependsOnNamedParameter<T%>(#this, x, a: a);
+static method _extension#0|_earlierUnnamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, (self::_extension#0|_earlierUnnamedParameter::T%) → void x, self::_extension#0|_earlierUnnamedParameter::T% y) → void
+  return throw "";
+static method _extension#0|get#_earlierUnnamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>((T%) → void, T%) → void
+  return <T extends core::Object? = dynamic>((T%) → void x, T% y) → void => self::_extension#0|_earlierUnnamedParameter<T%>(#this, x, y);
+static method _extension#0|_laterNamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, {required self::_extension#0|_laterNamedParameter::T% a = #C1, required (self::_extension#0|_laterNamedParameter::T%) → void b = #C1}) → void
+  return throw "";
+static method _extension#0|get#_laterNamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>({a: T%, b: (T%) → void}) → void
+  return <T extends core::Object? = dynamic>({T% a = #C1, (T%) → void b = #C1}) → void => self::_extension#0|_laterNamedParameter<T%>(#this, a: a, b: b);
+static method _extension#0|_earlierNamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, {required (self::_extension#0|_earlierNamedParameter::T%) → void a = #C1, required self::_extension#0|_earlierNamedParameter::T% b = #C1}) → void
+  return throw "";
+static method _extension#0|get#_earlierNamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>({a: (T%) → void, b: T%}) → void
+  return <T extends core::Object? = dynamic>({(T%) → void a = #C1, T% b = #C1}) → void => self::_extension#0|_earlierNamedParameter<T%>(#this, a: a, b: b);
+static method _extension#0|_earlierNamedParameterDependsOnUnnamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_earlierNamedParameterDependsOnUnnamedParameter::T% b, {required (self::_extension#0|_earlierNamedParameterDependsOnUnnamedParameter::T%) → void a = #C1}) → void
+  return throw "";
+static method _extension#0|get#_earlierNamedParameterDependsOnUnnamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>(T%, {a: (T%) → void}) → void
+  return <T extends core::Object? = dynamic>(T% b, {(T%) → void a = #C1}) → void => self::_extension#0|_earlierNamedParameterDependsOnUnnamedParameter<T%>(#this, b, a: a);
+static method _extension#0|_propagateToReturnType<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_propagateToReturnType::T% x, (self::_extension#0|_propagateToReturnType::T%) → self::_extension#0|_propagateToReturnType::U% y) → self::_extension#0|_propagateToReturnType::U%
+  return throw "";
+static method _extension#0|get#_propagateToReturnType(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(T%, (T%) → U%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(T% x, (T%) → U% y) → U% => self::_extension#0|_propagateToReturnType<T%, U%>(#this, x, y);
+static method _extension#0|_closureAsParameterType<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_closureAsParameterType::T% x, (self::_extension#0|_closureAsParameterType::T%) → self::_extension#0|_closureAsParameterType::U% y) → self::_extension#0|_closureAsParameterType::U%
+  return throw "";
+static method _extension#0|get#_closureAsParameterType(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(T%, (T%) → U%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(T% x, (T%) → U% y) → U% => self::_extension#0|_closureAsParameterType<T%, U%>(#this, x, y);
+static method _extension#0|_propagateToEarlierClosure<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, (self::_extension#0|_propagateToEarlierClosure::T%) → self::_extension#0|_propagateToEarlierClosure::U% x, () → self::_extension#0|_propagateToEarlierClosure::T% y) → self::_extension#0|_propagateToEarlierClosure::U%
+  return throw "";
+static method _extension#0|get#_propagateToEarlierClosure(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>((T%) → U%, () → T%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>((T%) → U% x, () → T% y) → U% => self::_extension#0|_propagateToEarlierClosure<T%, U%>(#this, x, y);
+static method _extension#0|_propagateToLaterClosure<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, () → self::_extension#0|_propagateToLaterClosure::T% x, (self::_extension#0|_propagateToLaterClosure::T%) → self::_extension#0|_propagateToLaterClosure::U% y) → self::_extension#0|_propagateToLaterClosure::U%
+  return throw "";
+static method _extension#0|get#_propagateToLaterClosure(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → T%, (T%) → U%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → T% x, (T%) → U% y) → U% => self::_extension#0|_propagateToLaterClosure<T%, U%>(#this, x, y);
+static method _extension#0|get#_longDependencyChain(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic, V extends core::Object? = dynamic>(() → T%, (T%) → U%, (U%) → V%) → V%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic, V extends core::Object? = dynamic>(() → T% x, (T%) → U% y, (U%) → V% z) → V% => self::_extension#0|_longDependencyChain<T%, U%, V%>(#this, x, y, z);
+static method _extension#0|_longDependencyChain<T extends core::Object? = dynamic, U extends core::Object? = dynamic, V extends core::Object? = dynamic>(lowered final core::int #this, () → self::_extension#0|_longDependencyChain::T% x, (self::_extension#0|_longDependencyChain::T%) → self::_extension#0|_longDependencyChain::U% y, (self::_extension#0|_longDependencyChain::U%) → self::_extension#0|_longDependencyChain::V% z) → self::_extension#0|_longDependencyChain::V%
+  return throw "";
+static method _extension#0|_dependencyCycle<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, (self::_extension#0|_dependencyCycle::U%) → self::_extension#0|_dependencyCycle::T% x, (self::_extension#0|_dependencyCycle::T%) → self::_extension#0|_dependencyCycle::U% y) → core::Map<self::_extension#0|_dependencyCycle::T%, self::_extension#0|_dependencyCycle::U%>
+  return throw "";
+static method _extension#0|get#_dependencyCycle(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>((U%) → T%, (T%) → U%) → core::Map<T%, U%>
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>((U%) → T% x, (T%) → U% y) → core::Map<T%, U%> => self::_extension#0|_dependencyCycle<T%, U%>(#this, x, y);
+static method _extension#0|_propagateFromContravariantReturnType<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, () → (self::_extension#0|_propagateFromContravariantReturnType::T%) → void x, (self::_extension#0|_propagateFromContravariantReturnType::T%) → self::_extension#0|_propagateFromContravariantReturnType::U% y) → self::_extension#0|_propagateFromContravariantReturnType::U%
+  return throw "";
+static method _extension#0|get#_propagateFromContravariantReturnType(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → (T%) → void, (T%) → U%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → (T%) → void x, (T%) → U% y) → U% => self::_extension#0|_propagateFromContravariantReturnType<T%, U%>(#this, x, y);
+static method _extension#0|_propagateToContravariantParameterType<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, () → self::_extension#0|_propagateToContravariantParameterType::T% x, ((self::_extension#0|_propagateToContravariantParameterType::T%) → void) → self::_extension#0|_propagateToContravariantParameterType::U% y) → self::_extension#0|_propagateToContravariantParameterType::U%
+  return throw "";
+static method _extension#0|get#_propagateToContravariantParameterType(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → T%, ((T%) → void) → U%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → T% x, ((T%) → void) → U% y) → U% => self::_extension#0|_propagateToContravariantParameterType<T%, U%>(#this, x, y);
+static method _extension#0|_returnTypeRefersToMultipleTypeVars<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, () → core::Map<self::_extension#0|_returnTypeRefersToMultipleTypeVars::T%, self::_extension#0|_returnTypeRefersToMultipleTypeVars::U%> x, (self::_extension#0|_returnTypeRefersToMultipleTypeVars::T%) → void y, (self::_extension#0|_returnTypeRefersToMultipleTypeVars::U%) → void z) → void
+  return throw "";
+static method _extension#0|get#_returnTypeRefersToMultipleTypeVars(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → core::Map<T%, U%>, (T%) → void, (U%) → void) → void
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → core::Map<T%, U%> x, (T%) → void y, (U%) → void z) → void => self::_extension#0|_returnTypeRefersToMultipleTypeVars<T%, U%>(#this, x, y, z);
+static method _extension#0|_unnecessaryDueToNoDependency<T extends core::Object? = dynamic>(lowered final core::int #this, () → self::_extension#0|_unnecessaryDueToNoDependency::T% x, self::_extension#0|_unnecessaryDueToNoDependency::T% y) → self::_extension#0|_unnecessaryDueToNoDependency::T%
+  return throw "";
+static method _extension#0|get#_unnecessaryDueToNoDependency(lowered final core::int #this) → <T extends core::Object? = dynamic>(() → T%, T%) → T%
+  return <T extends core::Object? = dynamic>(() → T% x, T% y) → T% => self::_extension#0|_unnecessaryDueToNoDependency<T%>(#this, x, y);
+static method _extension#0|_unnecessaryDueToExplicitParameterTypeNamed<T extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed::T% x, ({required x: self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed::T%, required y: core::int}) → self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed::T% y) → self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed::T%
+  return throw "";
+static method _extension#0|get#_unnecessaryDueToExplicitParameterTypeNamed(lowered final core::int #this) → <T extends core::Object? = dynamic>(T%, ({required x: T%, required y: core::int}) → T%) → T%
+  return <T extends core::Object? = dynamic>(T% x, ({required x: T%, required y: core::int}) → T% y) → T% => self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed<T%>(#this, x, y);
+static method _extension#0|_parenthesized<T extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_parenthesized::T% x, (self::_extension#0|_parenthesized::T%) → void y) → void
+  return throw "";
+static method _extension#0|get#_parenthesized(lowered final core::int #this) → <T extends core::Object? = dynamic>(T%, (T%) → void) → void
+  return <T extends core::Object? = dynamic>(T% x, (T%) → void y) → void => self::_extension#0|_parenthesized<T%>(#this, x, y);
+static method _extension#0|_parenthesizedNamed<T extends core::Object? = dynamic>(lowered final core::int #this, {required self::_extension#0|_parenthesizedNamed::T% a = #C1, required (self::_extension#0|_parenthesizedNamed::T%) → void b = #C1}) → void
+  return throw "";
+static method _extension#0|get#_parenthesizedNamed(lowered final core::int #this) → <T extends core::Object? = dynamic>({a: T%, b: (T%) → void}) → void
+  return <T extends core::Object? = dynamic>({T% a = #C1, (T%) → void b = #C1}) → void => self::_extension#0|_parenthesizedNamed<T%>(#this, a: a, b: b);
+static method _extension#0|_parenthesizedTwice<T extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_parenthesizedTwice::T% x, (self::_extension#0|_parenthesizedTwice::T%) → void y) → void
+  return throw "";
+static method _extension#0|get#_parenthesizedTwice(lowered final core::int #this) → <T extends core::Object? = dynamic>(T%, (T%) → void) → void
+  return <T extends core::Object? = dynamic>(T% x, (T%) → void y) → void => self::_extension#0|_parenthesizedTwice<T%>(#this, x, y);
+static method _extension#0|_parenthesizedTwiceNamed<T extends core::Object? = dynamic>(lowered final core::int #this, {required self::_extension#0|_parenthesizedTwiceNamed::T% a = #C1, required (self::_extension#0|_parenthesizedTwiceNamed::T%) → void b = #C1}) → void
+  return throw "";
+static method _extension#0|get#_parenthesizedTwiceNamed(lowered final core::int #this) → <T extends core::Object? = dynamic>({a: T%, b: (T%) → void}) → void
+  return <T extends core::Object? = dynamic>({T% a = #C1, (T%) → void b = #C1}) → void => self::_extension#0|_parenthesizedTwiceNamed<T%>(#this, a: a, b: b);
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/inference_update_1/horizontal_inference_extension_method.dart.weak.outline.expect b/pkg/front_end/testcases/inference_update_1/horizontal_inference_extension_method.dart.weak.outline.expect
new file mode 100644
index 0000000..dae2ab4
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/horizontal_inference_extension_method.dart.weak.outline.expect
@@ -0,0 +1,176 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+extension _extension#0 on core::int {
+  method _laterUnnamedParameter = self::_extension#0|_laterUnnamedParameter;
+  tearoff _laterUnnamedParameter = self::_extension#0|get#_laterUnnamedParameter;
+  method _laterUnnamedParameterDependsOnNamedParameter = self::_extension#0|_laterUnnamedParameterDependsOnNamedParameter;
+  tearoff _laterUnnamedParameterDependsOnNamedParameter = self::_extension#0|get#_laterUnnamedParameterDependsOnNamedParameter;
+  method _earlierUnnamedParameter = self::_extension#0|_earlierUnnamedParameter;
+  tearoff _earlierUnnamedParameter = self::_extension#0|get#_earlierUnnamedParameter;
+  method _laterNamedParameter = self::_extension#0|_laterNamedParameter;
+  tearoff _laterNamedParameter = self::_extension#0|get#_laterNamedParameter;
+  method _earlierNamedParameter = self::_extension#0|_earlierNamedParameter;
+  tearoff _earlierNamedParameter = self::_extension#0|get#_earlierNamedParameter;
+  method _earlierNamedParameterDependsOnUnnamedParameter = self::_extension#0|_earlierNamedParameterDependsOnUnnamedParameter;
+  tearoff _earlierNamedParameterDependsOnUnnamedParameter = self::_extension#0|get#_earlierNamedParameterDependsOnUnnamedParameter;
+  method _propagateToReturnType = self::_extension#0|_propagateToReturnType;
+  tearoff _propagateToReturnType = self::_extension#0|get#_propagateToReturnType;
+  method _closureAsParameterType = self::_extension#0|_closureAsParameterType;
+  tearoff _closureAsParameterType = self::_extension#0|get#_closureAsParameterType;
+  method _propagateToEarlierClosure = self::_extension#0|_propagateToEarlierClosure;
+  tearoff _propagateToEarlierClosure = self::_extension#0|get#_propagateToEarlierClosure;
+  method _propagateToLaterClosure = self::_extension#0|_propagateToLaterClosure;
+  tearoff _propagateToLaterClosure = self::_extension#0|get#_propagateToLaterClosure;
+  method _longDependencyChain = self::_extension#0|_longDependencyChain;
+  tearoff _longDependencyChain = self::_extension#0|get#_longDependencyChain;
+  method _dependencyCycle = self::_extension#0|_dependencyCycle;
+  tearoff _dependencyCycle = self::_extension#0|get#_dependencyCycle;
+  method _propagateFromContravariantReturnType = self::_extension#0|_propagateFromContravariantReturnType;
+  tearoff _propagateFromContravariantReturnType = self::_extension#0|get#_propagateFromContravariantReturnType;
+  method _propagateToContravariantParameterType = self::_extension#0|_propagateToContravariantParameterType;
+  tearoff _propagateToContravariantParameterType = self::_extension#0|get#_propagateToContravariantParameterType;
+  method _returnTypeRefersToMultipleTypeVars = self::_extension#0|_returnTypeRefersToMultipleTypeVars;
+  tearoff _returnTypeRefersToMultipleTypeVars = self::_extension#0|get#_returnTypeRefersToMultipleTypeVars;
+  method _unnecessaryDueToNoDependency = self::_extension#0|_unnecessaryDueToNoDependency;
+  tearoff _unnecessaryDueToNoDependency = self::_extension#0|get#_unnecessaryDueToNoDependency;
+  method _unnecessaryDueToExplicitParameterTypeNamed = self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed;
+  tearoff _unnecessaryDueToExplicitParameterTypeNamed = self::_extension#0|get#_unnecessaryDueToExplicitParameterTypeNamed;
+  method _parenthesized = self::_extension#0|_parenthesized;
+  tearoff _parenthesized = self::_extension#0|get#_parenthesized;
+  method _parenthesizedNamed = self::_extension#0|_parenthesizedNamed;
+  tearoff _parenthesizedNamed = self::_extension#0|get#_parenthesizedNamed;
+  method _parenthesizedTwice = self::_extension#0|_parenthesizedTwice;
+  tearoff _parenthesizedTwice = self::_extension#0|get#_parenthesizedTwice;
+  method _parenthesizedTwiceNamed = self::_extension#0|_parenthesizedTwiceNamed;
+  tearoff _parenthesizedTwiceNamed = self::_extension#0|get#_parenthesizedTwiceNamed;
+}
+static method testLaterUnnamedParameter(core::int i) → dynamic
+  ;
+static method testLaterUnnamedParameterDependsOnNamedParameter(core::int i) → dynamic
+  ;
+static method testEarlierUnnamedParameter(core::int i) → dynamic
+  ;
+static method testLaterNamedParameter(core::int i) → dynamic
+  ;
+static method testEarlierNamedParameter(core::int i) → dynamic
+  ;
+static method testEarlierNamedParameterDependsOnUnnamedParameter(core::int i) → dynamic
+  ;
+static method testPropagateToReturnType(core::int i) → dynamic
+  ;
+static method testClosureAsParameterType(core::int i) → dynamic
+  ;
+static method testPropagateToEarlierClosure(core::int i) → dynamic
+  ;
+static method testPropagateToLaterClosure(core::int i) → dynamic
+  ;
+static method testLongDependencyChain(core::int i) → dynamic
+  ;
+static method testDependencyCycle(core::int i) → dynamic
+  ;
+static method testPropagateFromContravariantReturnType(core::int i) → dynamic
+  ;
+static method testPropagateToContravariantParameterType(core::int i) → dynamic
+  ;
+static method testReturnTypeRefersToMultipleTypeVars(core::int i) → dynamic
+  ;
+static method testUnnecessaryDueToNoDependency(core::int i) → dynamic
+  ;
+static method testUnnecessaryDueToExplicitParameterTypeNamed(core::int i) → dynamic
+  ;
+static method testParenthesized(core::int i) → dynamic
+  ;
+static method testParenthesizedNamed(core::int i) → dynamic
+  ;
+static method testParenthesizedTwice(core::int i) → dynamic
+  ;
+static method testParenthesizedTwiceNamed(core::int i) → dynamic
+  ;
+static method _extension#0|_laterUnnamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_laterUnnamedParameter::T% x, (self::_extension#0|_laterUnnamedParameter::T%) → void y) → self::_extension#0|_laterUnnamedParameter::T%
+  ;
+static method _extension#0|get#_laterUnnamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>(T%, (T%) → void) → T%
+  return <T extends core::Object? = dynamic>(T% x, (T%) → void y) → T% => self::_extension#0|_laterUnnamedParameter<T%>(#this, x, y);
+static method _extension#0|_laterUnnamedParameterDependsOnNamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, (self::_extension#0|_laterUnnamedParameterDependsOnNamedParameter::T%) → void x, {required self::_extension#0|_laterUnnamedParameterDependsOnNamedParameter::T% a}) → void
+  ;
+static method _extension#0|get#_laterUnnamedParameterDependsOnNamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>((T%) → void, {a: T%}) → void
+  return <T extends core::Object? = dynamic>((T%) → void x, {T% a}) → void => self::_extension#0|_laterUnnamedParameterDependsOnNamedParameter<T%>(#this, x, a: a);
+static method _extension#0|_earlierUnnamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, (self::_extension#0|_earlierUnnamedParameter::T%) → void x, self::_extension#0|_earlierUnnamedParameter::T% y) → void
+  ;
+static method _extension#0|get#_earlierUnnamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>((T%) → void, T%) → void
+  return <T extends core::Object? = dynamic>((T%) → void x, T% y) → void => self::_extension#0|_earlierUnnamedParameter<T%>(#this, x, y);
+static method _extension#0|_laterNamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, {required self::_extension#0|_laterNamedParameter::T% a, required (self::_extension#0|_laterNamedParameter::T%) → void b}) → void
+  ;
+static method _extension#0|get#_laterNamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>({a: T%, b: (T%) → void}) → void
+  return <T extends core::Object? = dynamic>({T% a, (T%) → void b}) → void => self::_extension#0|_laterNamedParameter<T%>(#this, a: a, b: b);
+static method _extension#0|_earlierNamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, {required (self::_extension#0|_earlierNamedParameter::T%) → void a, required self::_extension#0|_earlierNamedParameter::T% b}) → void
+  ;
+static method _extension#0|get#_earlierNamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>({a: (T%) → void, b: T%}) → void
+  return <T extends core::Object? = dynamic>({(T%) → void a, T% b}) → void => self::_extension#0|_earlierNamedParameter<T%>(#this, a: a, b: b);
+static method _extension#0|_earlierNamedParameterDependsOnUnnamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_earlierNamedParameterDependsOnUnnamedParameter::T% b, {required (self::_extension#0|_earlierNamedParameterDependsOnUnnamedParameter::T%) → void a}) → void
+  ;
+static method _extension#0|get#_earlierNamedParameterDependsOnUnnamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>(T%, {a: (T%) → void}) → void
+  return <T extends core::Object? = dynamic>(T% b, {(T%) → void a}) → void => self::_extension#0|_earlierNamedParameterDependsOnUnnamedParameter<T%>(#this, b, a: a);
+static method _extension#0|_propagateToReturnType<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_propagateToReturnType::T% x, (self::_extension#0|_propagateToReturnType::T%) → self::_extension#0|_propagateToReturnType::U% y) → self::_extension#0|_propagateToReturnType::U%
+  ;
+static method _extension#0|get#_propagateToReturnType(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(T%, (T%) → U%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(T% x, (T%) → U% y) → U% => self::_extension#0|_propagateToReturnType<T%, U%>(#this, x, y);
+static method _extension#0|_closureAsParameterType<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_closureAsParameterType::T% x, (self::_extension#0|_closureAsParameterType::T%) → self::_extension#0|_closureAsParameterType::U% y) → self::_extension#0|_closureAsParameterType::U%
+  ;
+static method _extension#0|get#_closureAsParameterType(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(T%, (T%) → U%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(T% x, (T%) → U% y) → U% => self::_extension#0|_closureAsParameterType<T%, U%>(#this, x, y);
+static method _extension#0|_propagateToEarlierClosure<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, (self::_extension#0|_propagateToEarlierClosure::T%) → self::_extension#0|_propagateToEarlierClosure::U% x, () → self::_extension#0|_propagateToEarlierClosure::T% y) → self::_extension#0|_propagateToEarlierClosure::U%
+  ;
+static method _extension#0|get#_propagateToEarlierClosure(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>((T%) → U%, () → T%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>((T%) → U% x, () → T% y) → U% => self::_extension#0|_propagateToEarlierClosure<T%, U%>(#this, x, y);
+static method _extension#0|_propagateToLaterClosure<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, () → self::_extension#0|_propagateToLaterClosure::T% x, (self::_extension#0|_propagateToLaterClosure::T%) → self::_extension#0|_propagateToLaterClosure::U% y) → self::_extension#0|_propagateToLaterClosure::U%
+  ;
+static method _extension#0|get#_propagateToLaterClosure(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → T%, (T%) → U%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → T% x, (T%) → U% y) → U% => self::_extension#0|_propagateToLaterClosure<T%, U%>(#this, x, y);
+static method _extension#0|get#_longDependencyChain(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic, V extends core::Object? = dynamic>(() → T%, (T%) → U%, (U%) → V%) → V%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic, V extends core::Object? = dynamic>(() → T% x, (T%) → U% y, (U%) → V% z) → V% => self::_extension#0|_longDependencyChain<T%, U%, V%>(#this, x, y, z);
+static method _extension#0|_longDependencyChain<T extends core::Object? = dynamic, U extends core::Object? = dynamic, V extends core::Object? = dynamic>(lowered final core::int #this, () → self::_extension#0|_longDependencyChain::T% x, (self::_extension#0|_longDependencyChain::T%) → self::_extension#0|_longDependencyChain::U% y, (self::_extension#0|_longDependencyChain::U%) → self::_extension#0|_longDependencyChain::V% z) → self::_extension#0|_longDependencyChain::V%
+  ;
+static method _extension#0|_dependencyCycle<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, (self::_extension#0|_dependencyCycle::U%) → self::_extension#0|_dependencyCycle::T% x, (self::_extension#0|_dependencyCycle::T%) → self::_extension#0|_dependencyCycle::U% y) → core::Map<self::_extension#0|_dependencyCycle::T%, self::_extension#0|_dependencyCycle::U%>
+  ;
+static method _extension#0|get#_dependencyCycle(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>((U%) → T%, (T%) → U%) → core::Map<T%, U%>
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>((U%) → T% x, (T%) → U% y) → core::Map<T%, U%> => self::_extension#0|_dependencyCycle<T%, U%>(#this, x, y);
+static method _extension#0|_propagateFromContravariantReturnType<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, () → (self::_extension#0|_propagateFromContravariantReturnType::T%) → void x, (self::_extension#0|_propagateFromContravariantReturnType::T%) → self::_extension#0|_propagateFromContravariantReturnType::U% y) → self::_extension#0|_propagateFromContravariantReturnType::U%
+  ;
+static method _extension#0|get#_propagateFromContravariantReturnType(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → (T%) → void, (T%) → U%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → (T%) → void x, (T%) → U% y) → U% => self::_extension#0|_propagateFromContravariantReturnType<T%, U%>(#this, x, y);
+static method _extension#0|_propagateToContravariantParameterType<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, () → self::_extension#0|_propagateToContravariantParameterType::T% x, ((self::_extension#0|_propagateToContravariantParameterType::T%) → void) → self::_extension#0|_propagateToContravariantParameterType::U% y) → self::_extension#0|_propagateToContravariantParameterType::U%
+  ;
+static method _extension#0|get#_propagateToContravariantParameterType(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → T%, ((T%) → void) → U%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → T% x, ((T%) → void) → U% y) → U% => self::_extension#0|_propagateToContravariantParameterType<T%, U%>(#this, x, y);
+static method _extension#0|_returnTypeRefersToMultipleTypeVars<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, () → core::Map<self::_extension#0|_returnTypeRefersToMultipleTypeVars::T%, self::_extension#0|_returnTypeRefersToMultipleTypeVars::U%> x, (self::_extension#0|_returnTypeRefersToMultipleTypeVars::T%) → void y, (self::_extension#0|_returnTypeRefersToMultipleTypeVars::U%) → void z) → void
+  ;
+static method _extension#0|get#_returnTypeRefersToMultipleTypeVars(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → core::Map<T%, U%>, (T%) → void, (U%) → void) → void
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → core::Map<T%, U%> x, (T%) → void y, (U%) → void z) → void => self::_extension#0|_returnTypeRefersToMultipleTypeVars<T%, U%>(#this, x, y, z);
+static method _extension#0|_unnecessaryDueToNoDependency<T extends core::Object? = dynamic>(lowered final core::int #this, () → self::_extension#0|_unnecessaryDueToNoDependency::T% x, self::_extension#0|_unnecessaryDueToNoDependency::T% y) → self::_extension#0|_unnecessaryDueToNoDependency::T%
+  ;
+static method _extension#0|get#_unnecessaryDueToNoDependency(lowered final core::int #this) → <T extends core::Object? = dynamic>(() → T%, T%) → T%
+  return <T extends core::Object? = dynamic>(() → T% x, T% y) → T% => self::_extension#0|_unnecessaryDueToNoDependency<T%>(#this, x, y);
+static method _extension#0|_unnecessaryDueToExplicitParameterTypeNamed<T extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed::T% x, ({required x: self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed::T%, required y: core::int}) → self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed::T% y) → self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed::T%
+  ;
+static method _extension#0|get#_unnecessaryDueToExplicitParameterTypeNamed(lowered final core::int #this) → <T extends core::Object? = dynamic>(T%, ({required x: T%, required y: core::int}) → T%) → T%
+  return <T extends core::Object? = dynamic>(T% x, ({required x: T%, required y: core::int}) → T% y) → T% => self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed<T%>(#this, x, y);
+static method _extension#0|_parenthesized<T extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_parenthesized::T% x, (self::_extension#0|_parenthesized::T%) → void y) → void
+  ;
+static method _extension#0|get#_parenthesized(lowered final core::int #this) → <T extends core::Object? = dynamic>(T%, (T%) → void) → void
+  return <T extends core::Object? = dynamic>(T% x, (T%) → void y) → void => self::_extension#0|_parenthesized<T%>(#this, x, y);
+static method _extension#0|_parenthesizedNamed<T extends core::Object? = dynamic>(lowered final core::int #this, {required self::_extension#0|_parenthesizedNamed::T% a, required (self::_extension#0|_parenthesizedNamed::T%) → void b}) → void
+  ;
+static method _extension#0|get#_parenthesizedNamed(lowered final core::int #this) → <T extends core::Object? = dynamic>({a: T%, b: (T%) → void}) → void
+  return <T extends core::Object? = dynamic>({T% a, (T%) → void b}) → void => self::_extension#0|_parenthesizedNamed<T%>(#this, a: a, b: b);
+static method _extension#0|_parenthesizedTwice<T extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_parenthesizedTwice::T% x, (self::_extension#0|_parenthesizedTwice::T%) → void y) → void
+  ;
+static method _extension#0|get#_parenthesizedTwice(lowered final core::int #this) → <T extends core::Object? = dynamic>(T%, (T%) → void) → void
+  return <T extends core::Object? = dynamic>(T% x, (T%) → void y) → void => self::_extension#0|_parenthesizedTwice<T%>(#this, x, y);
+static method _extension#0|_parenthesizedTwiceNamed<T extends core::Object? = dynamic>(lowered final core::int #this, {required self::_extension#0|_parenthesizedTwiceNamed::T% a, required (self::_extension#0|_parenthesizedTwiceNamed::T%) → void b}) → void
+  ;
+static method _extension#0|get#_parenthesizedTwiceNamed(lowered final core::int #this) → <T extends core::Object? = dynamic>({a: T%, b: (T%) → void}) → void
+  return <T extends core::Object? = dynamic>({T% a, (T%) → void b}) → void => self::_extension#0|_parenthesizedTwiceNamed<T%>(#this, a: a, b: b);
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference_update_1/horizontal_inference_extension_method.dart.weak.transformed.expect b/pkg/front_end/testcases/inference_update_1/horizontal_inference_extension_method.dart.weak.transformed.expect
new file mode 100644
index 0000000..af2047a
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/horizontal_inference_extension_method.dart.weak.transformed.expect
@@ -0,0 +1,232 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+extension _extension#0 on core::int {
+  method _laterUnnamedParameter = self::_extension#0|_laterUnnamedParameter;
+  tearoff _laterUnnamedParameter = self::_extension#0|get#_laterUnnamedParameter;
+  method _laterUnnamedParameterDependsOnNamedParameter = self::_extension#0|_laterUnnamedParameterDependsOnNamedParameter;
+  tearoff _laterUnnamedParameterDependsOnNamedParameter = self::_extension#0|get#_laterUnnamedParameterDependsOnNamedParameter;
+  method _earlierUnnamedParameter = self::_extension#0|_earlierUnnamedParameter;
+  tearoff _earlierUnnamedParameter = self::_extension#0|get#_earlierUnnamedParameter;
+  method _laterNamedParameter = self::_extension#0|_laterNamedParameter;
+  tearoff _laterNamedParameter = self::_extension#0|get#_laterNamedParameter;
+  method _earlierNamedParameter = self::_extension#0|_earlierNamedParameter;
+  tearoff _earlierNamedParameter = self::_extension#0|get#_earlierNamedParameter;
+  method _earlierNamedParameterDependsOnUnnamedParameter = self::_extension#0|_earlierNamedParameterDependsOnUnnamedParameter;
+  tearoff _earlierNamedParameterDependsOnUnnamedParameter = self::_extension#0|get#_earlierNamedParameterDependsOnUnnamedParameter;
+  method _propagateToReturnType = self::_extension#0|_propagateToReturnType;
+  tearoff _propagateToReturnType = self::_extension#0|get#_propagateToReturnType;
+  method _closureAsParameterType = self::_extension#0|_closureAsParameterType;
+  tearoff _closureAsParameterType = self::_extension#0|get#_closureAsParameterType;
+  method _propagateToEarlierClosure = self::_extension#0|_propagateToEarlierClosure;
+  tearoff _propagateToEarlierClosure = self::_extension#0|get#_propagateToEarlierClosure;
+  method _propagateToLaterClosure = self::_extension#0|_propagateToLaterClosure;
+  tearoff _propagateToLaterClosure = self::_extension#0|get#_propagateToLaterClosure;
+  method _longDependencyChain = self::_extension#0|_longDependencyChain;
+  tearoff _longDependencyChain = self::_extension#0|get#_longDependencyChain;
+  method _dependencyCycle = self::_extension#0|_dependencyCycle;
+  tearoff _dependencyCycle = self::_extension#0|get#_dependencyCycle;
+  method _propagateFromContravariantReturnType = self::_extension#0|_propagateFromContravariantReturnType;
+  tearoff _propagateFromContravariantReturnType = self::_extension#0|get#_propagateFromContravariantReturnType;
+  method _propagateToContravariantParameterType = self::_extension#0|_propagateToContravariantParameterType;
+  tearoff _propagateToContravariantParameterType = self::_extension#0|get#_propagateToContravariantParameterType;
+  method _returnTypeRefersToMultipleTypeVars = self::_extension#0|_returnTypeRefersToMultipleTypeVars;
+  tearoff _returnTypeRefersToMultipleTypeVars = self::_extension#0|get#_returnTypeRefersToMultipleTypeVars;
+  method _unnecessaryDueToNoDependency = self::_extension#0|_unnecessaryDueToNoDependency;
+  tearoff _unnecessaryDueToNoDependency = self::_extension#0|get#_unnecessaryDueToNoDependency;
+  method _unnecessaryDueToExplicitParameterTypeNamed = self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed;
+  tearoff _unnecessaryDueToExplicitParameterTypeNamed = self::_extension#0|get#_unnecessaryDueToExplicitParameterTypeNamed;
+  method _parenthesized = self::_extension#0|_parenthesized;
+  tearoff _parenthesized = self::_extension#0|get#_parenthesized;
+  method _parenthesizedNamed = self::_extension#0|_parenthesizedNamed;
+  tearoff _parenthesizedNamed = self::_extension#0|get#_parenthesizedNamed;
+  method _parenthesizedTwice = self::_extension#0|_parenthesizedTwice;
+  tearoff _parenthesizedTwice = self::_extension#0|get#_parenthesizedTwice;
+  method _parenthesizedTwiceNamed = self::_extension#0|_parenthesizedTwiceNamed;
+  tearoff _parenthesizedTwiceNamed = self::_extension#0|get#_parenthesizedTwiceNamed;
+}
+static method testLaterUnnamedParameter(core::int i) → dynamic {
+  self::_extension#0|_laterUnnamedParameter<core::int>(i, 0, (core::int x) → void {
+    x;
+  });
+}
+static method testLaterUnnamedParameterDependsOnNamedParameter(core::int i) → dynamic {
+  self::_extension#0|_laterUnnamedParameterDependsOnNamedParameter<core::int>(i, (core::int x) → void {
+    x;
+  }, a: 0);
+}
+static method testEarlierUnnamedParameter(core::int i) → dynamic {
+  self::_extension#0|_earlierUnnamedParameter<core::int>(i, (core::int x) → void {
+    x;
+  }, 0);
+}
+static method testLaterNamedParameter(core::int i) → dynamic {
+  self::_extension#0|_laterNamedParameter<core::int>(i, a: 0, b: (core::int x) → void {
+    x;
+  });
+}
+static method testEarlierNamedParameter(core::int i) → dynamic {
+  self::_extension#0|_earlierNamedParameter<core::int>(i, a: (core::int x) → void {
+    x;
+  }, b: 0);
+}
+static method testEarlierNamedParameterDependsOnUnnamedParameter(core::int i) → dynamic {
+  self::_extension#0|_earlierNamedParameterDependsOnUnnamedParameter<core::int>(i, 0, a: (core::int x) → void {
+    x;
+  });
+}
+static method testPropagateToReturnType(core::int i) → dynamic {
+  self::_extension#0|_propagateToReturnType<core::int, core::List<core::int>>(i, 0, (core::int x) → core::List<core::int> => core::_GrowableList::_literal1<core::int>(x));
+}
+static method testClosureAsParameterType(core::int i) → dynamic {
+  self::_extension#0|_closureAsParameterType<() → core::int, core::List<core::int>>(i, () → core::int => 0, (() → core::int h) → core::List<core::int> => core::_GrowableList::_literal1<core::int>(h(){() → core::int}));
+}
+static method testPropagateToEarlierClosure(core::int i) → dynamic {
+  self::_extension#0|_propagateToEarlierClosure<core::int, core::List<core::int>>(i, (core::int x) → core::List<core::int> => core::_GrowableList::_literal1<core::int>(x), () → core::int => 0);
+}
+static method testPropagateToLaterClosure(core::int i) → dynamic {
+  self::_extension#0|_propagateToLaterClosure<core::int, core::List<core::int>>(i, () → core::int => 0, (core::int x) → core::List<core::int> => core::_GrowableList::_literal1<core::int>(x));
+}
+static method testLongDependencyChain(core::int i) → dynamic {
+  self::_extension#0|_longDependencyChain<core::List<core::int>, core::int, core::Set<core::int>>(i, () → core::List<core::int> => core::_GrowableList::_literal1<core::int>(0), (core::List<core::int> x) → core::int => x.{core::Iterable::single}{core::int}, (core::int y) → core::Set<core::int> => block {
+    final core::Set<core::int> #t1 = new col::_CompactLinkedHashSet::•<core::int>();
+    #t1.{core::Set::add}{Invariant}(y){(core::int) → core::bool};
+  } =>#t1);
+}
+static method testDependencyCycle(core::int i) → dynamic {
+  self::_extension#0|_dependencyCycle<core::List<core::Object?>, core::Set<core::Object?>>(i, (core::Object? x) → core::List<core::Object?> => core::_GrowableList::_literal1<core::Object?>(x), (core::Object? y) → core::Set<core::Object?> => block {
+    final core::Set<core::Object?> #t2 = new col::_CompactLinkedHashSet::•<core::Object?>();
+    #t2.{core::Set::add}{Invariant}(y){(core::Object?) → core::bool};
+  } =>#t2);
+}
+static method testPropagateFromContravariantReturnType(core::int i) → dynamic {
+  self::_extension#0|_propagateFromContravariantReturnType<core::int, core::List<core::int>>(i, () → (core::int) → void => (core::int i) → void {}, (core::int x) → core::List<core::int> => core::_GrowableList::_literal1<core::int>(x));
+}
+static method testPropagateToContravariantParameterType(core::int i) → dynamic {
+  self::_extension#0|_propagateToContravariantParameterType<core::int, core::List<(core::int) → void>>(i, () → core::int => 0, ((core::int) → void x) → core::List<(core::int) → void> => core::_GrowableList::_literal1<(core::int) → void>(x));
+}
+static method testReturnTypeRefersToMultipleTypeVars(core::int i) → dynamic {
+  self::_extension#0|_returnTypeRefersToMultipleTypeVars<core::int, core::String>(i, () → core::Map<core::int, core::String> => <core::int, core::String>{0: ""}, (core::int k) → void {
+    k;
+  }, (core::String v) → void {
+    v;
+  });
+}
+static method testUnnecessaryDueToNoDependency(core::int i) → dynamic {
+  self::_extension#0|_unnecessaryDueToNoDependency<core::int?>(i, () → core::int => 0, null);
+}
+static method testUnnecessaryDueToExplicitParameterTypeNamed(core::int i) → dynamic {
+  core::int? a = self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed<core::int?>(i, null, ({core::int? x = #C1, required core::int y = #C1}) → core::int => (let final core::int? #t3 = x in #t3 == null ?{core::int} 0 : #t3{core::int}).{core::num::+}(y){(core::num) → core::int});
+  a;
+}
+static method testParenthesized(core::int i) → dynamic {
+  self::_extension#0|_parenthesized<core::int>(i, 0, (core::int x) → void {
+    x;
+  });
+}
+static method testParenthesizedNamed(core::int i) → dynamic {
+  self::_extension#0|_parenthesizedNamed<core::int>(i, a: 0, b: (core::int x) → void {
+    x;
+  });
+}
+static method testParenthesizedTwice(core::int i) → dynamic {
+  self::_extension#0|_parenthesizedTwice<core::int>(i, 0, (core::int x) → void {
+    x;
+  });
+}
+static method testParenthesizedTwiceNamed(core::int i) → dynamic {
+  self::_extension#0|_parenthesizedTwiceNamed<core::int>(i, a: 0, b: (core::int x) → void {
+    x;
+  });
+}
+static method _extension#0|_laterUnnamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_laterUnnamedParameter::T% x, (self::_extension#0|_laterUnnamedParameter::T%) → void y) → self::_extension#0|_laterUnnamedParameter::T%
+  return throw "";
+static method _extension#0|get#_laterUnnamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>(T%, (T%) → void) → T%
+  return <T extends core::Object? = dynamic>(T% x, (T%) → void y) → T% => self::_extension#0|_laterUnnamedParameter<T%>(#this, x, y);
+static method _extension#0|_laterUnnamedParameterDependsOnNamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, (self::_extension#0|_laterUnnamedParameterDependsOnNamedParameter::T%) → void x, {required self::_extension#0|_laterUnnamedParameterDependsOnNamedParameter::T% a = #C1}) → void
+  return throw "";
+static method _extension#0|get#_laterUnnamedParameterDependsOnNamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>((T%) → void, {a: T%}) → void
+  return <T extends core::Object? = dynamic>((T%) → void x, {T% a = #C1}) → void => self::_extension#0|_laterUnnamedParameterDependsOnNamedParameter<T%>(#this, x, a: a);
+static method _extension#0|_earlierUnnamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, (self::_extension#0|_earlierUnnamedParameter::T%) → void x, self::_extension#0|_earlierUnnamedParameter::T% y) → void
+  return throw "";
+static method _extension#0|get#_earlierUnnamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>((T%) → void, T%) → void
+  return <T extends core::Object? = dynamic>((T%) → void x, T% y) → void => self::_extension#0|_earlierUnnamedParameter<T%>(#this, x, y);
+static method _extension#0|_laterNamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, {required self::_extension#0|_laterNamedParameter::T% a = #C1, required (self::_extension#0|_laterNamedParameter::T%) → void b = #C1}) → void
+  return throw "";
+static method _extension#0|get#_laterNamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>({a: T%, b: (T%) → void}) → void
+  return <T extends core::Object? = dynamic>({T% a = #C1, (T%) → void b = #C1}) → void => self::_extension#0|_laterNamedParameter<T%>(#this, a: a, b: b);
+static method _extension#0|_earlierNamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, {required (self::_extension#0|_earlierNamedParameter::T%) → void a = #C1, required self::_extension#0|_earlierNamedParameter::T% b = #C1}) → void
+  return throw "";
+static method _extension#0|get#_earlierNamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>({a: (T%) → void, b: T%}) → void
+  return <T extends core::Object? = dynamic>({(T%) → void a = #C1, T% b = #C1}) → void => self::_extension#0|_earlierNamedParameter<T%>(#this, a: a, b: b);
+static method _extension#0|_earlierNamedParameterDependsOnUnnamedParameter<T extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_earlierNamedParameterDependsOnUnnamedParameter::T% b, {required (self::_extension#0|_earlierNamedParameterDependsOnUnnamedParameter::T%) → void a = #C1}) → void
+  return throw "";
+static method _extension#0|get#_earlierNamedParameterDependsOnUnnamedParameter(lowered final core::int #this) → <T extends core::Object? = dynamic>(T%, {a: (T%) → void}) → void
+  return <T extends core::Object? = dynamic>(T% b, {(T%) → void a = #C1}) → void => self::_extension#0|_earlierNamedParameterDependsOnUnnamedParameter<T%>(#this, b, a: a);
+static method _extension#0|_propagateToReturnType<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_propagateToReturnType::T% x, (self::_extension#0|_propagateToReturnType::T%) → self::_extension#0|_propagateToReturnType::U% y) → self::_extension#0|_propagateToReturnType::U%
+  return throw "";
+static method _extension#0|get#_propagateToReturnType(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(T%, (T%) → U%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(T% x, (T%) → U% y) → U% => self::_extension#0|_propagateToReturnType<T%, U%>(#this, x, y);
+static method _extension#0|_closureAsParameterType<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_closureAsParameterType::T% x, (self::_extension#0|_closureAsParameterType::T%) → self::_extension#0|_closureAsParameterType::U% y) → self::_extension#0|_closureAsParameterType::U%
+  return throw "";
+static method _extension#0|get#_closureAsParameterType(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(T%, (T%) → U%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(T% x, (T%) → U% y) → U% => self::_extension#0|_closureAsParameterType<T%, U%>(#this, x, y);
+static method _extension#0|_propagateToEarlierClosure<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, (self::_extension#0|_propagateToEarlierClosure::T%) → self::_extension#0|_propagateToEarlierClosure::U% x, () → self::_extension#0|_propagateToEarlierClosure::T% y) → self::_extension#0|_propagateToEarlierClosure::U%
+  return throw "";
+static method _extension#0|get#_propagateToEarlierClosure(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>((T%) → U%, () → T%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>((T%) → U% x, () → T% y) → U% => self::_extension#0|_propagateToEarlierClosure<T%, U%>(#this, x, y);
+static method _extension#0|_propagateToLaterClosure<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, () → self::_extension#0|_propagateToLaterClosure::T% x, (self::_extension#0|_propagateToLaterClosure::T%) → self::_extension#0|_propagateToLaterClosure::U% y) → self::_extension#0|_propagateToLaterClosure::U%
+  return throw "";
+static method _extension#0|get#_propagateToLaterClosure(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → T%, (T%) → U%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → T% x, (T%) → U% y) → U% => self::_extension#0|_propagateToLaterClosure<T%, U%>(#this, x, y);
+static method _extension#0|get#_longDependencyChain(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic, V extends core::Object? = dynamic>(() → T%, (T%) → U%, (U%) → V%) → V%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic, V extends core::Object? = dynamic>(() → T% x, (T%) → U% y, (U%) → V% z) → V% => self::_extension#0|_longDependencyChain<T%, U%, V%>(#this, x, y, z);
+static method _extension#0|_longDependencyChain<T extends core::Object? = dynamic, U extends core::Object? = dynamic, V extends core::Object? = dynamic>(lowered final core::int #this, () → self::_extension#0|_longDependencyChain::T% x, (self::_extension#0|_longDependencyChain::T%) → self::_extension#0|_longDependencyChain::U% y, (self::_extension#0|_longDependencyChain::U%) → self::_extension#0|_longDependencyChain::V% z) → self::_extension#0|_longDependencyChain::V%
+  return throw "";
+static method _extension#0|_dependencyCycle<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, (self::_extension#0|_dependencyCycle::U%) → self::_extension#0|_dependencyCycle::T% x, (self::_extension#0|_dependencyCycle::T%) → self::_extension#0|_dependencyCycle::U% y) → core::Map<self::_extension#0|_dependencyCycle::T%, self::_extension#0|_dependencyCycle::U%>
+  return throw "";
+static method _extension#0|get#_dependencyCycle(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>((U%) → T%, (T%) → U%) → core::Map<T%, U%>
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>((U%) → T% x, (T%) → U% y) → core::Map<T%, U%> => self::_extension#0|_dependencyCycle<T%, U%>(#this, x, y);
+static method _extension#0|_propagateFromContravariantReturnType<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, () → (self::_extension#0|_propagateFromContravariantReturnType::T%) → void x, (self::_extension#0|_propagateFromContravariantReturnType::T%) → self::_extension#0|_propagateFromContravariantReturnType::U% y) → self::_extension#0|_propagateFromContravariantReturnType::U%
+  return throw "";
+static method _extension#0|get#_propagateFromContravariantReturnType(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → (T%) → void, (T%) → U%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → (T%) → void x, (T%) → U% y) → U% => self::_extension#0|_propagateFromContravariantReturnType<T%, U%>(#this, x, y);
+static method _extension#0|_propagateToContravariantParameterType<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, () → self::_extension#0|_propagateToContravariantParameterType::T% x, ((self::_extension#0|_propagateToContravariantParameterType::T%) → void) → self::_extension#0|_propagateToContravariantParameterType::U% y) → self::_extension#0|_propagateToContravariantParameterType::U%
+  return throw "";
+static method _extension#0|get#_propagateToContravariantParameterType(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → T%, ((T%) → void) → U%) → U%
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → T% x, ((T%) → void) → U% y) → U% => self::_extension#0|_propagateToContravariantParameterType<T%, U%>(#this, x, y);
+static method _extension#0|_returnTypeRefersToMultipleTypeVars<T extends core::Object? = dynamic, U extends core::Object? = dynamic>(lowered final core::int #this, () → core::Map<self::_extension#0|_returnTypeRefersToMultipleTypeVars::T%, self::_extension#0|_returnTypeRefersToMultipleTypeVars::U%> x, (self::_extension#0|_returnTypeRefersToMultipleTypeVars::T%) → void y, (self::_extension#0|_returnTypeRefersToMultipleTypeVars::U%) → void z) → void
+  return throw "";
+static method _extension#0|get#_returnTypeRefersToMultipleTypeVars(lowered final core::int #this) → <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → core::Map<T%, U%>, (T%) → void, (U%) → void) → void
+  return <T extends core::Object? = dynamic, U extends core::Object? = dynamic>(() → core::Map<T%, U%> x, (T%) → void y, (U%) → void z) → void => self::_extension#0|_returnTypeRefersToMultipleTypeVars<T%, U%>(#this, x, y, z);
+static method _extension#0|_unnecessaryDueToNoDependency<T extends core::Object? = dynamic>(lowered final core::int #this, () → self::_extension#0|_unnecessaryDueToNoDependency::T% x, self::_extension#0|_unnecessaryDueToNoDependency::T% y) → self::_extension#0|_unnecessaryDueToNoDependency::T%
+  return throw "";
+static method _extension#0|get#_unnecessaryDueToNoDependency(lowered final core::int #this) → <T extends core::Object? = dynamic>(() → T%, T%) → T%
+  return <T extends core::Object? = dynamic>(() → T% x, T% y) → T% => self::_extension#0|_unnecessaryDueToNoDependency<T%>(#this, x, y);
+static method _extension#0|_unnecessaryDueToExplicitParameterTypeNamed<T extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed::T% x, ({required x: self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed::T%, required y: core::int}) → self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed::T% y) → self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed::T%
+  return throw "";
+static method _extension#0|get#_unnecessaryDueToExplicitParameterTypeNamed(lowered final core::int #this) → <T extends core::Object? = dynamic>(T%, ({required x: T%, required y: core::int}) → T%) → T%
+  return <T extends core::Object? = dynamic>(T% x, ({required x: T%, required y: core::int}) → T% y) → T% => self::_extension#0|_unnecessaryDueToExplicitParameterTypeNamed<T%>(#this, x, y);
+static method _extension#0|_parenthesized<T extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_parenthesized::T% x, (self::_extension#0|_parenthesized::T%) → void y) → void
+  return throw "";
+static method _extension#0|get#_parenthesized(lowered final core::int #this) → <T extends core::Object? = dynamic>(T%, (T%) → void) → void
+  return <T extends core::Object? = dynamic>(T% x, (T%) → void y) → void => self::_extension#0|_parenthesized<T%>(#this, x, y);
+static method _extension#0|_parenthesizedNamed<T extends core::Object? = dynamic>(lowered final core::int #this, {required self::_extension#0|_parenthesizedNamed::T% a = #C1, required (self::_extension#0|_parenthesizedNamed::T%) → void b = #C1}) → void
+  return throw "";
+static method _extension#0|get#_parenthesizedNamed(lowered final core::int #this) → <T extends core::Object? = dynamic>({a: T%, b: (T%) → void}) → void
+  return <T extends core::Object? = dynamic>({T% a = #C1, (T%) → void b = #C1}) → void => self::_extension#0|_parenthesizedNamed<T%>(#this, a: a, b: b);
+static method _extension#0|_parenthesizedTwice<T extends core::Object? = dynamic>(lowered final core::int #this, self::_extension#0|_parenthesizedTwice::T% x, (self::_extension#0|_parenthesizedTwice::T%) → void y) → void
+  return throw "";
+static method _extension#0|get#_parenthesizedTwice(lowered final core::int #this) → <T extends core::Object? = dynamic>(T%, (T%) → void) → void
+  return <T extends core::Object? = dynamic>(T% x, (T%) → void y) → void => self::_extension#0|_parenthesizedTwice<T%>(#this, x, y);
+static method _extension#0|_parenthesizedTwiceNamed<T extends core::Object? = dynamic>(lowered final core::int #this, {required self::_extension#0|_parenthesizedTwiceNamed::T% a = #C1, required (self::_extension#0|_parenthesizedTwiceNamed::T%) → void b = #C1}) → void
+  return throw "";
+static method _extension#0|get#_parenthesizedTwiceNamed(lowered final core::int #this) → <T extends core::Object? = dynamic>({a: T%, b: (T%) → void}) → void
+  return <T extends core::Object? = dynamic>({T% a = #C1, (T%) → void b = #C1}) → void => self::_extension#0|_parenthesizedTwiceNamed<T%>(#this, a: a, b: b);
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index 0f8cabf..d71457b 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -339,10 +339,10 @@
 #endif  // !defined(ARCH_IS_64_BIT) && !defined(FFI_UNIT_TESTS)
 #elif defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM) ||                 \
     defined(TARGET_ARCH_RISCV32)
-#if defined(HOST_ARCH_X64) && defined(TARGET_ARCH_ARM)
-// This is simarm_x64, which is the only case where host/target architecture
-// mismatch is allowed. Unless, we're running FFI unit tests.
-#define IS_SIMARM_X64 1
+#if defined(ARCH_IS_64_BIT) && defined(TARGET_ARCH_ARM)
+// This is simarm_x64 or simarm_arm64, which is the only case where host/target
+// architecture mismatch is allowed. Unless, we're running FFI unit tests.
+#define IS_SIMARM_HOST64 1
 #elif !defined(ARCH_IS_32_BIT) && !defined(FFI_UNIT_TESTS)
 #error Mismatched Host/Target architectures.
 #endif  // !defined(ARCH_IS_32_BIT) && !defined(FFI_UNIT_TESTS)
@@ -360,7 +360,7 @@
 #elif defined(TARGET_ARCH_ARM)
 #if !defined(HOST_ARCH_ARM)
 #define TARGET_HOST_MISMATCH 1
-#if !defined(IS_SIMARM_X64)
+#if !defined(IS_SIMARM_HOST64)
 #define USING_SIMULATOR 1
 #endif
 #endif
diff --git a/runtime/vm/compiler/assembler/disassembler_arm.cc b/runtime/vm/compiler/assembler/disassembler_arm.cc
index 51bb568..4d860a5 100644
--- a/runtime/vm/compiler/assembler/disassembler_arm.cc
+++ b/runtime/vm/compiler/assembler/disassembler_arm.cc
@@ -1512,14 +1512,14 @@
 
   *object = NULL;
   // TODO(36839): Make DecodeLoadObjectFromPoolOrThread work on simarm_x64.
-#if !defined(IS_SIMARM_X64)
+#if !defined(IS_SIMARM_HOST64)
   if (!code.IsNull()) {
     *object = &Object::Handle();
     if (!DecodeLoadObjectFromPoolOrThread(pc, code, *object)) {
       *object = NULL;
     }
   }
-#endif  // !defined(IS_SIMARM_X64)
+#endif  // !defined(IS_SIMARM_HOST64)
 }
 
 #endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index bf4c995..2ccf215 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -155,7 +155,7 @@
 static DartInitializationState init_state_;
 
 static void CheckOffsets() {
-#if !defined(IS_SIMARM_X64)
+#if !defined(IS_SIMARM_HOST64)
   // These offsets are embedded in precompiled instructions. We need the
   // compiler and the runtime to agree.
   bool ok = true;
@@ -241,7 +241,7 @@
 #undef CHECK_CONSTANT
 #undef CHECK_OFFSET
 #undef CHECK_PAYLOAD_SIZEOF
-#endif  // !defined(IS_SIMARM_X64)
+#endif  // !defined(IS_SIMARM_HOST64)
 }
 
 char* Dart::DartInit(const Dart_InitializeParams* params) {
diff --git a/runtime/vm/globals.h b/runtime/vm/globals.h
index c564a48..559dc44 100644
--- a/runtime/vm/globals.h
+++ b/runtime/vm/globals.h
@@ -112,7 +112,7 @@
 #define SUPPORT_TIMELINE 1
 #endif
 
-#if defined(ARCH_IS_64_BIT) && !defined(IS_SIMARM_X64)
+#if defined(ARCH_IS_64_BIT) && !defined(IS_SIMARM_HOST64)
 #define HASH_IN_OBJECT_HEADER 1
 #endif
 
diff --git a/tests/language/inference_update_1/downward_inference_preferred_over_horizontal_test.dart b/tests/language/inference_update_1/downward_inference_preferred_over_horizontal_test.dart
new file mode 100644
index 0000000..704d642
--- /dev/null
+++ b/tests/language/inference_update_1/downward_inference_preferred_over_horizontal_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Tests that when the feature is enabled, types supplied by downward inference
+// are preferred over those available via horizontal inference.
+//
+// The way this happens is that the type parameter is "fixed" after the downward
+// inference phase and is not changed in further inference phases.
+
+// SharedOptions=--enable-experiment=inference-update-1
+
+import '../static_type_helper.dart';
+
+testProductOfNums(List<num> values) {
+  num a = values.fold(
+      1,
+      (p, v) =>
+          (p..expectStaticType<Exactly<num>>()) *
+          (v..expectStaticType<Exactly<num>>()))
+    ..expectStaticType<Exactly<num>>();
+}
+
+main() {}
diff --git a/tests/language/inference_update_1/horizontal_inference_extension_method_test.dart b/tests/language/inference_update_1/horizontal_inference_extension_method_test.dart
new file mode 100644
index 0000000..346be23
--- /dev/null
+++ b/tests/language/inference_update_1/horizontal_inference_extension_method_test.dart
@@ -0,0 +1,214 @@
+// 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.
+
+// Tests that horizontal inference works properly when the invocation is an
+// extension member.  This is an important corner case because the front end
+// adds an implicit `this` argument to extension members as part of the lowering
+// process.  We need to make sure that the dependency tracking logic properly
+// accounts for this extra argument.
+
+// SharedOptions=--enable-experiment=inference-update-1
+
+import '../static_type_helper.dart';
+
+testLaterUnnamedParameter(int i) {
+  i._laterUnnamedParameter(0, (x) {
+    x.expectStaticType<Exactly<int>>();
+  });
+}
+
+/// This special case verifies that the implementations correctly associate the
+/// zeroth positional parameter with the corresponding argument (even if that
+/// argument isn't in the zeroth position at the call site).
+testLaterUnnamedParameterDependsOnNamedParameter(int i) {
+  i._laterUnnamedParameterDependsOnNamedParameter(a: 0, (x) {
+    x.expectStaticType<Exactly<int>>();
+  });
+}
+
+testEarlierUnnamedParameter(int i) {
+  i._earlierUnnamedParameter((x) {
+    x.expectStaticType<Exactly<int>>();
+  }, 0);
+}
+
+testLaterNamedParameter(int i) {
+  i._laterNamedParameter(
+      a: 0,
+      b: (x) {
+        x.expectStaticType<Exactly<int>>();
+      });
+}
+
+testEarlierNamedParameter(int i) {
+  i._earlierNamedParameter(
+      a: (x) {
+        x.expectStaticType<Exactly<int>>();
+      },
+      b: 0);
+}
+
+/// This special case verifies that the implementations correctly associate the
+/// zeroth positional parameter with the corresponding argument (even if that
+/// argument isn't in the zeroth position at the call site).
+testEarlierNamedParameterDependsOnUnnamedParameter(int i) {
+  i._earlierNamedParameterDependsOnUnnamedParameter(a: (x) {
+    x.expectStaticType<Exactly<int>>();
+  }, 0);
+}
+
+testPropagateToReturnType(int i) {
+  i
+      ._propagateToReturnType(0, (x) => [x])
+      .expectStaticType<Exactly<List<int>>>();
+}
+
+// The test cases below exercise situations where there are multiple closures in
+// the invocation, and they need to be inferred in the right order.
+
+testClosureAsParameterType(int i) {
+  i
+      ._closureAsParameterType(
+          () => 0, (h) => [h()]..expectStaticType<Exactly<List<int>>>())
+      .expectStaticType<Exactly<List<int>>>();
+}
+
+testPropagateToEarlierClosure(int i) {
+  i
+      ._propagateToEarlierClosure(
+          (x) => [x]..expectStaticType<Exactly<List<int>>>(), () => 0)
+      .expectStaticType<Exactly<List<int>>>();
+}
+
+testPropagateToLaterClosure(int i) {
+  i
+      ._propagateToLaterClosure(
+          () => 0, (x) => [x]..expectStaticType<Exactly<List<int>>>())
+      .expectStaticType<Exactly<List<int>>>();
+}
+
+testLongDependencyChain(int i) {
+  i
+      ._longDependencyChain(
+          () => [0],
+          (x) => x.single..expectStaticType<Exactly<int>>(),
+          (y) => {y}..expectStaticType<Exactly<Set<int>>>())
+      .expectStaticType<Exactly<Set<int>>>();
+}
+
+testDependencyCycle(int i) {
+  i
+      ._dependencyCycle((x) => [x]..expectStaticType<Exactly<List<Object?>>>(),
+          (y) => {y}..expectStaticType<Exactly<Set<Object?>>>())
+      .expectStaticType<Exactly<Map<List<Object?>, Set<Object?>>>>();
+}
+
+testPropagateFromContravariantReturnType(int i) {
+  i
+      ._propagateFromContravariantReturnType(
+          () => (int i) {}, (x) => [x]..expectStaticType<Exactly<List<int>>>())
+      .expectStaticType<Exactly<List<int>>>();
+}
+
+testPropagateToContravariantParameterType(int i) {
+  i
+      ._propagateToContravariantParameterType(() => 0,
+          (x) => [x]..expectStaticType<Exactly<List<void Function(int)>>>())
+      .expectStaticType<Exactly<List<void Function(int)>>>();
+}
+
+testReturnTypeRefersToMultipleTypeVars(int i) {
+  i._returnTypeRefersToMultipleTypeVars(() => {0: ''}, (k) {
+    k.expectStaticType<Exactly<int>>();
+  }, (v) {
+    v.expectStaticType<Exactly<String>>();
+  });
+}
+
+testUnnecessaryDueToNoDependency(int i) {
+  i
+      ._unnecessaryDueToNoDependency(() => 0, null)
+      .expectStaticType<Exactly<int?>>();
+}
+
+testUnnecessaryDueToExplicitParameterTypeNamed(int i) {
+  var a = i._unnecessaryDueToExplicitParameterTypeNamed(
+      null, ({int? x, required y}) => (x ?? 0) + y);
+  a.expectStaticType<Exactly<int?>>();
+}
+
+testParenthesized(int i) {
+  i._parenthesized(0, ((x) {
+    x.expectStaticType<Exactly<int>>();
+  }));
+}
+
+testParenthesizedNamed(int i) {
+  i._parenthesizedNamed(
+      a: 0,
+      b: ((x) {
+        x.expectStaticType<Exactly<int>>();
+      }));
+}
+
+testParenthesizedTwice(int i) {
+  i._parenthesizedTwice(0, (((x) {
+    x.expectStaticType<Exactly<int>>();
+  })));
+}
+
+testParenthesizedTwiceNamed(int i) {
+  i._parenthesizedTwiceNamed(
+      a: 0,
+      b: (((x) {
+        x.expectStaticType<Exactly<int>>();
+      })));
+}
+
+extension on int {
+  T _laterUnnamedParameter<T>(T x, void Function(T) y) => throw '';
+  void _laterUnnamedParameterDependsOnNamedParameter<T>(void Function(T) x,
+          {required T a}) =>
+      throw '';
+  void _earlierUnnamedParameter<T>(void Function(T) x, T y) => throw '';
+  void _laterNamedParameter<T>({required T a, required void Function(T) b}) =>
+      throw '';
+  void _earlierNamedParameter<T>({required void Function(T) a, required T b}) =>
+      throw '';
+  void _earlierNamedParameterDependsOnUnnamedParameter<T>(T b,
+          {required void Function(T) a}) =>
+      throw '';
+  U _propagateToReturnType<T, U>(T x, U Function(T) y) => throw '';
+  U _closureAsParameterType<T, U>(T x, U Function(T) y) => throw '';
+  U _propagateToEarlierClosure<T, U>(U Function(T) x, T Function() y) =>
+      throw '';
+  U _propagateToLaterClosure<T, U>(T Function() x, U Function(T) y) => throw '';
+  V _longDependencyChain<T, U, V>(
+          T Function() x, U Function(T) y, V Function(U) z) =>
+      throw '';
+  Map<T, U> _dependencyCycle<T, U>(T Function(U) x, U Function(T) y) =>
+      throw '';
+  U _propagateFromContravariantReturnType<T, U>(
+          void Function(T) Function() x, U Function(T) y) =>
+      throw '';
+  U _propagateToContravariantParameterType<T, U>(
+          T Function() x, U Function(void Function(T)) y) =>
+      throw '';
+  void _returnTypeRefersToMultipleTypeVars<T, U>(
+          Map<T, U> Function() x, void Function(T) y, void Function(U) z) =>
+      throw '';
+  T _unnecessaryDueToNoDependency<T>(T Function() x, T y) => throw '';
+  T _unnecessaryDueToExplicitParameterTypeNamed<T>(
+          T x, T Function({required T x, required int y}) y) =>
+      throw '';
+  void _parenthesized<T>(T x, void Function(T) y) => throw '';
+  void _parenthesizedNamed<T>({required T a, required void Function(T) b}) =>
+      throw '';
+  void _parenthesizedTwice<T>(T x, void Function(T) y) => throw '';
+  void _parenthesizedTwiceNamed<T>(
+          {required T a, required void Function(T) b}) =>
+      throw '';
+}
+
+main() {}
diff --git a/tools/VERSION b/tools/VERSION
index 65f3e26..2d8ba76 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 18
 PATCH 0
-PRERELEASE 102
+PRERELEASE 103
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index c7bcc68..53e919c 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -3402,6 +3402,15 @@
           ]
         },
         {
+          "name": "analyze pkg/dart2native",
+          "script": "out/ReleaseX64/dart-sdk/bin/dart",
+          "arguments": [
+            "analyze",
+            "--fatal-infos",
+            "pkg/dart2native"
+          ]
+        },
+        {
           "name": "analyze pkg/dartdev",
           "script": "out/ReleaseX64/dart-sdk/bin/dart",
           "arguments": [
diff --git a/tools/gn.py b/tools/gn.py
index a89e8a3..647f045 100755
--- a/tools/gn.py
+++ b/tools/gn.py
@@ -67,61 +67,82 @@
     return [merge(x, y) for x, y in gn_args.items()]
 
 
-# Runs true if the currently executing python interpreter is running under
-# Rosetta. I.e., python3 is an x64 executable and we're on an arm64 Mac.
-def IsRosetta():
-    if platform.system() == 'Darwin':
-        p = subprocess.Popen(['sysctl', '-in', 'sysctl.proc_translated'],
-                             stdout=subprocess.PIPE,
-                             stderr=subprocess.STDOUT)
-        output, _ = p.communicate()
-        return output.decode('utf-8').strip() == '1'
-    return False
-
-
+# The C compiler's host.
 def HostCpuForArch(arch):
-    # Check for Rosetta before checking platform.machine(), as the latter
-    # returns 'x86_64' when running under Rosetta.
-    if IsRosetta():
-        if arch in ['x64', 'x64c']:
-            # Without this case, we would try to build with
-            #   host_cpu="arm64"
-            #   target_cpu="x64"
-            #   dart_target_arch="x64"
-            # Which requires the VM to use an x64 simulator in the host
-            # arm64 binaries, and this simulator is unimplemented.
-            return 'x64'
-        else:
-            return 'arm64'
-
-    m = platform.machine()
-    if m == 'aarch64' or m == 'arm64':
-        return 'arm64'
-    if m == 'armv7l':
-        return 'arm'
-
-    if arch in ['ia32', 'arm', 'simarm', 'simarm_x64', 'riscv32', 'simriscv32']:
-        return 'x86'
-    if arch in [
-            'x64', 'arm64', 'simarm64', 'arm_x64', 'x64c', 'arm64c',
-            'simarm64c', 'riscv64', 'simriscv64'
-    ]:
+    if arch.endswith('_x64'):
         return 'x64'
+    if arch.endswith('_arm64'):
+        return 'arm64'
+    if arch.endswith('_riscv64'):
+        return 'riscv64'
+
+    # For each target architecture, we prefer in descending order
+    # - using the same architecture for the host (supports all architectures)
+    # - using a host architecture with the same word size (supports arm and riscv, which have simulators)
+    # - using a host architecture with a different word size (supports only AOT and only 32-bit target on 64-bit host)
+    if arch in ['ia32']:
+        candidates = ['x86']
+    elif arch in ['x64', 'x64c']:
+        candidates = ['x64']
+    elif arch in ['arm', 'simarm']:
+        candidates = ['arm', 'x86', 'riscv32', 'arm64', 'x64', 'riscv64']
+    elif arch in ['arm64', 'arm64c', 'simarm64', 'simarm64c']:
+        candidates = ['arm64', 'x64', 'riscv64']
+    elif arch in ['riscv32', 'simriscv32']:
+        candidates = ['riscv32', 'arm', 'x86', 'riscv64', 'arm64', 'x64']
+    elif arch in ['riscv64', 'simriscv64']:
+        candidates = ['riscv64', 'arm64', 'x64']
+    else:
+        raise Exception("Unknown Dart architecture: %s" % arch)
+
+    available = utils.HostArchitectures()
+    for candidate in candidates:
+        if candidate in available:
+            return candidate
+
+    raise Exception(
+        "Failed to find a C host architecture for %s. Need one of %s but only %s are available."
+        % (arch, candidates, available))
 
 
 # The C compiler's target.
 def TargetCpuForArch(arch, target_os):
-    if arch in ['ia32', 'simarm', 'simriscv32']:
+    # Real target architectures
+    if arch in ['ia32']:
         return 'x86'
-    if arch in [
-            'x64', 'simarm64', 'simarm_x64', 'simriscv64', 'x64c', 'simarm64c'
-    ]:
+    elif arch in ['x64', 'x64c']:
         return 'x64'
-    if arch == 'arm_x64':
+    elif arch in ['arm', 'arm_x64', 'arm_arm64', 'arm_riscv64']:
         return 'arm'
-    if arch == 'arm64c':
+    elif arch in ['arm64', 'arm64c']:
         return 'arm64'
-    return arch
+    elif arch in ['riscv32', 'riscv32_x64', 'riscv32_arm64', 'riscv32_riscv64']:
+        return 'riscv32'
+    elif arch in ['riscv64']:
+        return 'riscv64'
+
+    # Simulators
+    if arch in ['simarm_x64', 'simriscv32_x64']:
+        return 'x64'
+    elif arch in ['simarm_arm64', 'simriscv32_arm64']:
+        return 'arm64'
+    elif arch in ['simarm_riscv64', 'simriscv32_riscv64']:
+        return 'riscv64'
+    elif arch in ['simarm', 'simriscv32']:
+        candidates = ['arm', 'riscv32', 'x86']
+    elif arch in ['simarm64', 'simarm64c', 'simriscv64']:
+        candidates = ['arm64', 'riscv64', 'x64']
+    else:
+        raise Exception("Unknown Dart architecture: %s" % arch)
+
+    available = utils.HostArchitectures()
+    for candidate in candidates:
+        if candidate in available:
+            return candidate
+
+    raise Exception(
+        "Failed to find a C target architecture for %s. Need one of %s but only %s are available."
+        % (arch, candidates, available))
 
 
 # The Dart compiler's target.
@@ -130,7 +151,10 @@
         return 'ia32'
     if arch in ['x64', 'x64c']:
         return 'x64'
-    if arch in ['arm', 'simarm', 'simarm_x64', 'arm_x64']:
+    if arch in [
+            'arm', 'simarm', 'simarm_x64', 'arm_x64', 'simarm_arm64',
+            'arm_arm64'
+    ]:
         return 'arm'
     if arch in ['arm64', 'simarm64', 'arm64c', 'simarm64c']:
         return 'arm64'
diff --git a/tools/utils.py b/tools/utils.py
index 2f42263..d3401f1 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -67,9 +67,11 @@
     'arm': 'arm',
     'arm64': 'arm',
     'arm_x64': 'arm',
+    'arm_arm64': 'arm',
     'simarm': 'ia32',
     'simarm64': 'ia32',
     'simarm_x64': 'ia32',
+    'simarm_arm64': 'arm',
     'x64c': 'ia32',
     'arm64c': 'arm',
     'simarm64c': 'ia32',
@@ -149,27 +151,44 @@
     return None
 
 
+# Runs true if the currently executing python interpreter is running under
+# Rosetta. I.e., python3 is an x64 executable and we're on an arm64 Mac.
+def IsRosetta():
+    if platform.system() == 'Darwin':
+        p = subprocess.Popen(['sysctl', '-in', 'sysctl.proc_translated'],
+                             stdout=subprocess.PIPE,
+                             stderr=subprocess.STDOUT)
+        output, _ = p.communicate()
+        return output.decode('utf-8').strip() == '1'
+    return False
+
+
+# Returns the architectures that can run on the current machine.
+def HostArchitectures():
+    m = platform.machine()
+    if platform.system() == 'Darwin':
+        if m == 'arm64' or IsRosetta():
+            # ARM64 Macs also support X64.
+            return ['arm64', 'x64']
+        if m == 'x86_64':
+            # X64 Macs no longer support IA32.
+            return ['x64']
+    else:
+        if m in ['aarch64', 'arm64', 'arm64e']:
+            return ['arm64']
+        if m in ['armv7l']:
+            return ['arm']
+        if m in ['i386', 'i686', 'ia32', 'x86']:
+            return ['x86', 'ia32']
+        if m in ['x64', 'x86-64', 'x86_64', 'AMD64']:
+            return ['x64', 'x86', 'ia32']
+    raise Exception('Failed to determine host architectures for %s %s',
+                    platform.machine(), platform.system())
+
+
 # Try to guess the host architecture.
 def GuessArchitecture():
-    os_id = platform.machine()
-    if os_id.startswith('aarch64') or os_id == 'arm64':
-        return 'arm64'
-    elif os_id.startswith('arm'):
-        return 'arm'
-    elif '64' in os_id:
-        return 'x64'
-    elif (not os_id) or (not re.match('(x|i[3-6])86', os_id) is None):
-        return 'ia32'
-    elif os_id == 'i86pc':
-        return 'ia32'
-
-    guess_os = GuessOS()
-    print('Warning: Guessing architecture {} based on os {}\n'.format(
-        os_id, guess_os))
-    if guess_os == 'win32':
-        return 'ia32'
-    return None
-
+    return HostArchitectures()[0]
 
 # Try to guess the number of cpus on this machine.
 def GuessCpus():
@@ -242,9 +261,13 @@
 
 
 def IsCrossBuild(target_os, arch):
-    host_arch = GuessArchitecture()
-    return ((GetArchFamily(host_arch) != GetArchFamily(arch)) or
-            (target_os != GuessOS()))
+    if (target_os not in [None, 'host']) and (target_os != GuessOS()):
+        return True
+    if arch.startswith('sim'):
+        return False
+    if arch in HostArchitectures():
+        return False
+    return True
 
 
 def GetBuildConf(mode, arch, conf_os=None, sanitizer=None):
@@ -253,9 +276,8 @@
                                arch.upper())
 
     # Ask for a cross build if the host and target architectures don't match.
-    host_arch = GuessArchitecture()
     cross_build = ''
-    if GetArchFamily(host_arch) != GetArchFamily(arch):
+    if IsCrossBuild(conf_os, arch):
         cross_build = 'X'
     return '{}{}{}{}'.format(GetBuildMode(mode), GetBuildSanitizer(sanitizer),
                              cross_build, arch.upper())