Version 2.17.0-181.0.dev

Merge commit '1cdfaa85878a42444e026b823fdb356c6fd35612' into 'dev'
diff --git a/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
index 98fe2d9..46980c7 100644
--- a/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
@@ -2,36 +2,25 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/ast/extensions.dart';
-import 'package:analyzer/src/dart/element/member.dart';
-import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/type_algebra.dart';
-import 'package:analyzer/src/dart/resolver/instance_creation_resolver_helper.dart';
 import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
+import 'package:analyzer/src/dart/resolver/invocation_inferrer.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 
-class AnnotationResolver with InstanceCreationResolverMixin {
+class AnnotationResolver {
   final ResolverVisitor _resolver;
 
   AnnotationResolver(this._resolver);
 
-  @override
-  ResolverVisitor get resolver => _resolver;
-
   LibraryElement get _definingLibrary => _resolver.definingLibrary;
 
   ErrorReporter get _errorReporter => _resolver.errorReporter;
 
-  bool get _genericMetadataIsEnabled =>
-      _definingLibrary.featureSet.isEnabled(Feature.generic_metadata);
-
   void resolve(
       AnnotationImpl node, List<WhyNotPromotedGetter> whyNotPromotedList) {
     node.typeArguments?.accept(_resolver);
@@ -116,137 +105,35 @@
     constructorElement = _resolver.toLegacyElement(constructorElement);
     constructorName?.staticElement = constructorElement;
     node.element = constructorElement;
+    var annotationInferrer =
+        AnnotationInferrer(constructorName: constructorName);
 
     if (constructorElement == null) {
       _errorReporter.reportErrorForNode(
         CompileTimeErrorCode.INVALID_ANNOTATION,
         node,
       );
-      _resolver.analyzeArgumentList(argumentList, null,
+      annotationInferrer.resolveInvocation(
+          resolver: _resolver,
+          node: node,
+          rawType: null,
+          contextType: null,
           whyNotPromotedList: whyNotPromotedList);
       return;
     }
 
-    // If no type parameters, the elements are correct.
-    if (typeParameters.isEmpty) {
-      var typeArgumentList = node.typeArguments;
-      if (typeArgumentList != null) {
-        _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
-          typeArgumentList,
-          [
-            typeDisplayName,
-            typeParameters.length,
-            typeArgumentList.arguments.length,
-          ],
-        );
-      }
-      _resolveConstructorInvocationArguments(node);
-      _resolver.analyzeArgumentList(argumentList, constructorElement.parameters,
-          whyNotPromotedList: whyNotPromotedList);
-      return;
-    }
-
-    void resolveWithFixedTypeArguments(
-      List<DartType> typeArguments,
-      ConstructorElement constructorElement,
-    ) {
-      var type = instantiateElement(typeArguments);
-      constructorElement = ConstructorMember.from(constructorElement, type);
-      constructorName?.staticElement = constructorElement;
-      node.element = constructorElement;
-      _resolveConstructorInvocationArguments(node);
-
-      _resolver.analyzeArgumentList(argumentList, constructorElement.parameters,
-          whyNotPromotedList: whyNotPromotedList);
-    }
-
-    if (!_genericMetadataIsEnabled) {
-      var typeArguments = List.filled(
-        typeParameters.length,
-        DynamicTypeImpl.instance,
-      );
-      resolveWithFixedTypeArguments(typeArguments, constructorElement);
-      return;
-    }
-
-    var typeArgumentList = node.typeArguments;
-    if (typeArgumentList != null) {
-      List<DartType> typeArguments;
-      if (typeArgumentList.arguments.length == typeParameters.length) {
-        typeArguments = typeArgumentList.arguments
-            .map((element) => element.typeOrThrow)
-            .toList();
-        var substitution = Substitution.fromPairs(
-          typeParameters,
-          typeArguments,
-        );
-        for (var i = 0; i < typeParameters.length; i++) {
-          var typeParameter = typeParameters[i];
-          var bound = typeParameter.bound;
-          if (bound != null) {
-            bound = substitution.substituteType(bound);
-            var typeArgument = typeArguments[i];
-            if (!_resolver.typeSystem.isSubtypeOf(typeArgument, bound)) {
-              _errorReporter.reportErrorForNode(
-                CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
-                typeArgumentList.arguments[i],
-                [typeArgument, typeParameter.name, bound],
-              );
-            }
-          }
-        }
-      } else {
-        _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
-          typeArgumentList,
-          [
-            typeDisplayName,
-            typeParameters.length,
-            typeArgumentList.arguments.length,
-          ],
-        );
-        typeArguments = List.filled(
-          typeParameters.length,
-          DynamicTypeImpl.instance,
-        );
-      }
-      resolveWithFixedTypeArguments(typeArguments, constructorElement);
-      return;
-    }
-
     var elementToInfer = ConstructorElementToInfer(
       typeParameters,
       constructorElement,
     );
-    var inferenceResult = inferArgumentTypes(
-        inferenceNode: node,
-        constructorElement: constructorElement,
-        elementToInfer: elementToInfer,
-        typeArguments: node.typeArguments,
-        arguments: node.arguments!,
-        errorNode: node,
-        isConst: true,
-        contextReturnType: null);
-    if (inferenceResult != null) {
-      constructorElement = inferenceResult.constructorElement;
-    }
-    _resolver.analyzeArgumentList(argumentList, constructorElement.parameters,
-        whyNotPromotedList: whyNotPromotedList);
-
     var constructorRawType = elementToInfer.asType;
 
-    var inferred = _resolver.inferenceHelper.inferGenericInvoke(
-        node, constructorRawType, typeArgumentList, argumentList, node,
-        isConst: true, contextReturnType: null)!;
-
-    constructorElement = ConstructorMember.from(
-      constructorElement,
-      inferred.returnType as InterfaceType,
-    );
-    constructorName?.staticElement = constructorElement;
-    node.element = constructorElement;
-    _resolveConstructorInvocationArguments(node);
+    annotationInferrer.resolveInvocation(
+        resolver: _resolver,
+        node: node,
+        rawType: constructorRawType,
+        contextType: null,
+        whyNotPromotedList: whyNotPromotedList);
   }
 
   void _extensionGetter(
@@ -446,24 +333,6 @@
     }
   }
 
-  void _resolveConstructorInvocationArguments(AnnotationImpl node) {
-    var argumentList = node.arguments;
-    // error will be reported in ConstantVerifier
-    if (argumentList == null) {
-      return;
-    }
-    // resolve arguments to parameters
-    var constructor = node.element;
-    if (constructor is ConstructorElement) {
-      argumentList.correspondingStaticParameters =
-          ResolverVisitor.resolveArgumentsToParameters(
-        argumentList: argumentList,
-        parameters: constructor.parameters,
-        errorReporter: _errorReporter,
-      );
-    }
-  }
-
   void _typeAliasConstructorInvocation(
     AnnotationImpl node,
     TypeAliasElement typeAliasElement,
@@ -530,7 +399,11 @@
       AnnotationImpl node, List<WhyNotPromotedGetter> whyNotPromotedList) {
     var arguments = node.arguments;
     if (arguments != null) {
-      _resolver.analyzeArgumentList(arguments, null,
+      AnnotationInferrer(constructorName: null).resolveInvocation(
+          resolver: _resolver,
+          node: node,
+          rawType: null,
+          contextType: null,
           whyNotPromotedList: whyNotPromotedList);
     }
   }
diff --git a/pkg/analyzer/lib/src/dart/resolver/constructor_reference_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/constructor_reference_resolver.dart
index 7c09b9d..db7e1df 100644
--- a/pkg/analyzer/lib/src/dart/resolver/constructor_reference_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/constructor_reference_resolver.dart
@@ -97,7 +97,9 @@
     //
     // Otherwise we'll have a ConstructorElement, and we can skip inference
     // because there's nothing to infer in a non-generic type.
-    if (elementToInfer != null) {
+    if (elementToInfer != null &&
+        elementToInfer.typeParameters.isNotEmpty &&
+        constructorName.type.typeArguments == null) {
       // TODO(leafp): Currently, we may re-infer types here, since we
       // sometimes resolve multiple times.  We should really check that we
       // have not already inferred something.  However, the obvious ways to
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart
index 5a75cfd..ddbdfdb 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart
@@ -11,6 +11,7 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
 import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
+import 'package:analyzer/src/dart/resolver/invocation_inferrer.dart';
 import 'package:analyzer/src/dart/resolver/type_property_resolver.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/error/nullable_dereference_verifier.dart';
@@ -59,7 +60,8 @@
     }
 
     if (_checkForUseOfVoidResult(function, receiverType)) {
-      _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList);
+      _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList,
+          contextType: contextType);
       return;
     }
 
@@ -77,11 +79,13 @@
     if (identical(receiverType, NeverTypeImpl.instance)) {
       _errorReporter.reportErrorForNode(
           HintCode.RECEIVER_OF_TYPE_NEVER, function);
-      _unresolved(node, NeverTypeImpl.instance, whyNotPromotedList);
+      _unresolved(node, NeverTypeImpl.instance, whyNotPromotedList,
+          contextType: contextType);
       return;
     }
 
-    _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList);
+    _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList,
+        contextType: contextType);
   }
 
   /// Check for situations where the result of a method or function is used,
@@ -111,26 +115,19 @@
   void _resolve(FunctionExpressionInvocationImpl node, FunctionType rawType,
       List<WhyNotPromotedGetter> whyNotPromotedList,
       {required DartType? contextType}) {
-    _inferenceHelper.resolveFunctionExpressionInvocation(
+    var returnType =
+        const FunctionExpressionInvocationInferrer().resolveInvocation(
+      resolver: _resolver,
       node: node,
       rawType: rawType,
       whyNotPromotedList: whyNotPromotedList,
       contextType: contextType,
     );
 
-    var returnType = _inferenceHelper.computeInvokeReturnType(
-      node.staticInvokeType,
-    );
     _inferenceHelper.recordStaticType(node, returnType,
         contextType: contextType);
   }
 
-  void _resolveArguments(FunctionExpressionInvocationImpl node,
-      List<WhyNotPromotedGetter> whyNotPromotedList) {
-    _resolver.analyzeArgumentList(node.argumentList, null,
-        whyNotPromotedList: whyNotPromotedList);
-  }
-
   void _resolveReceiverExtensionOverride(FunctionExpressionInvocationImpl node,
       ExtensionOverride function, List<WhyNotPromotedGetter> whyNotPromotedList,
       {required DartType? contextType}) {
@@ -147,7 +144,8 @@
         function,
         [function.extensionName.name],
       );
-      return _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList);
+      return _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList,
+          contextType: contextType);
     }
 
     if (callElement.isStatic) {
@@ -183,7 +181,8 @@
           function,
         );
       }
-      _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList);
+      _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList,
+          contextType: contextType);
       return;
     }
 
@@ -192,7 +191,8 @@
         CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION,
         function,
       );
-      _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList);
+      _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList,
+          contextType: contextType);
       return;
     }
 
@@ -202,9 +202,15 @@
   }
 
   void _unresolved(FunctionExpressionInvocationImpl node, DartType type,
-      List<WhyNotPromotedGetter> whyNotPromotedList) {
+      List<WhyNotPromotedGetter> whyNotPromotedList,
+      {required DartType? contextType}) {
     _setExplicitTypeArgumentTypes(node);
-    _resolveArguments(node, whyNotPromotedList);
+    const FunctionExpressionInvocationInferrer().resolveInvocation(
+        resolver: _resolver,
+        node: node,
+        rawType: null,
+        contextType: contextType,
+        whyNotPromotedList: whyNotPromotedList);
     node.staticInvokeType = DynamicTypeImpl.instance;
     node.staticType = type;
   }
diff --git a/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart
index e139af8..bfdf73f 100644
--- a/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart
@@ -5,7 +5,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/resolver/instance_creation_resolver_helper.dart';
+import 'package:analyzer/src/dart/resolver/invocation_inferrer.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 
 /// A resolver for [InstanceCreationExpression] nodes.
@@ -14,15 +14,12 @@
 /// [InstanceCreationExpression] as a [MethodInvocation] if the parsed
 /// [ConstructorName]'s `type` resolves to a [FunctionReference] or
 /// [ConstructorReference], instead of a [NamedType].
-class InstanceCreationExpressionResolver with InstanceCreationResolverMixin {
+class InstanceCreationExpressionResolver {
   /// The resolver driving this participant.
   final ResolverVisitor _resolver;
 
   InstanceCreationExpressionResolver(this._resolver);
 
-  @override
-  ResolverVisitor get resolver => _resolver;
-
   void resolve(InstanceCreationExpressionImpl node,
       {required DartType? contextType}) {
     // The parser can parse certain code as [InstanceCreationExpression] when it
@@ -60,32 +57,20 @@
     constructorName.accept(_resolver);
     // Re-assign constructorName in case the node got replaced.
     constructorName = node.constructorName;
+    _resolver.elementResolver.visitInstanceCreationExpression(node);
     var elementToInfer = _resolver.inferenceHelper.constructorElementToInfer(
       constructorName: constructorName,
       definingLibrary: _resolver.definingLibrary,
     );
-    var typeName = constructorName.type;
-    var constructorElement = constructorName.staticElement;
-    var inferenceResult = inferArgumentTypes(
-        inferenceNode: node,
-        constructorElement: constructorElement,
-        elementToInfer: elementToInfer,
-        typeArguments: typeName.typeArguments,
-        arguments: node.argumentList,
-        errorNode: constructorName,
-        isConst: node.isConst,
-        contextReturnType: contextType);
-    if (inferenceResult != null) {
-      typeName.type = inferenceResult.constructedType;
-      constructorElement =
-          constructorName.staticElement = inferenceResult.constructorElement;
-    }
-    _resolver.analyzeArgumentList(
-        node.argumentList, constructorElement?.parameters,
+    const InstanceCreationInferrer().resolveInvocation(
+        resolver: _resolver,
+        node: node,
+        rawType: elementToInfer?.asType,
+        contextType: contextType,
         whyNotPromotedList: whyNotPromotedList);
-    _resolver.elementResolver.visitInstanceCreationExpression(node);
-    _resolver.typeAnalyzer
-        .visitInstanceCreationExpression(node, contextType: contextType);
+    _resolver.inferenceHelper.recordStaticType(
+        node, node.constructorName.type.type!,
+        contextType: contextType);
     _resolver.checkForArgumentTypesNotAssignableInList(
         node.argumentList, whyNotPromotedList);
   }
diff --git a/pkg/analyzer/lib/src/dart/resolver/instance_creation_resolver_helper.dart b/pkg/analyzer/lib/src/dart/resolver/instance_creation_resolver_helper.dart
deleted file mode 100644
index 0f99c2d..0000000
--- a/pkg/analyzer/lib/src/dart/resolver/instance_creation_resolver_helper.dart
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/element/member.dart';
-import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-
-/// Data constructor containing information about the result of performing type
-/// inference on an instance creation (either an InstanceCreationExpression or
-/// an Annotation that refers to a constructor).
-class InstanceCreationInferenceResult {
-  /// The refined constructor element (after type inference)
-  final ConstructorElement constructorElement;
-
-  /// The type that was constructed (after type inference)
-  final DartType constructedType;
-
-  InstanceCreationInferenceResult(
-      {required this.constructorElement, required this.constructedType});
-}
-
-/// Mixin containing shared functionality for resolving AST nodes that may
-/// create instances (InstanceCreationExpression and Annotation).
-mixin InstanceCreationResolverMixin {
-  ResolverVisitor get resolver;
-
-  /// Performs the first step of type inference for a constructor invocation.
-  InstanceCreationInferenceResult? inferArgumentTypes(
-      {required AstNode inferenceNode,
-      required ConstructorElement? constructorElement,
-      required ConstructorElementToInfer? elementToInfer,
-      required TypeArgumentListImpl? typeArguments,
-      required ArgumentListImpl arguments,
-      required AstNode errorNode,
-      required bool isConst,
-      required DartType? contextReturnType}) {
-    InstanceCreationInferenceResult? inferenceResult;
-    FunctionType? inferred;
-
-    // If the constructor is generic, we'll have a ConstructorMember that
-    // substitutes in type arguments (possibly `dynamic`) from earlier in
-    // resolution.
-    //
-    // Otherwise we'll have a ConstructorElement, and we can skip inference
-    // because there's nothing to infer in a non-generic type.
-    if (elementToInfer != null) {
-      // TODO(leafp): Currently, we may re-infer types here, since we
-      // sometimes resolve multiple times.  We should really check that we
-      // have not already inferred something.  However, the obvious ways to
-      // check this don't work, since we may have been instantiated
-      // to bounds in an earlier phase, and we *do* want to do inference
-      // in that case.
-
-      // Get back to the uninstantiated generic constructor.
-      // TODO(jmesserly): should we store this earlier in resolution?
-      // Or look it up, instead of jumping backwards through the Member?
-      var rawElement = elementToInfer.element;
-      var constructorType = elementToInfer.asType;
-
-      inferred = resolver.inferenceHelper.inferArgumentTypesForGeneric(
-          inferenceNode, constructorType, typeArguments,
-          isConst: isConst,
-          errorNode: errorNode,
-          contextReturnType: contextReturnType);
-
-      if (inferred != null) {
-        // Fix up the parameter elements based on inferred method.
-        arguments.correspondingStaticParameters =
-            ResolverVisitor.resolveArgumentsToParameters(
-          argumentList: arguments,
-          parameters: inferred.parameters,
-        );
-
-        // Update the static element as well. This is used in some cases, such
-        // as computing constant values. It is stored in two places.
-        constructorElement = ConstructorMember.from(
-          rawElement,
-          inferred.returnType as InterfaceType,
-        );
-        inferenceResult = InstanceCreationInferenceResult(
-            constructorElement: constructorElement,
-            constructedType: inferred.returnType);
-      }
-    }
-
-    if (inferred == null) {
-      if (constructorElement != null) {
-        var type = constructorElement.type;
-        type = resolver.toLegacyTypeIfOptOut(type) as FunctionType;
-      }
-    }
-
-    return inferenceResult;
-  }
-}
diff --git a/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart b/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
index 1e5f7a6..945c794 100644
--- a/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
@@ -9,12 +9,10 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/ast/extensions.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/type_algebra.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
-import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/dart/resolver/invocation_inferrer.dart';
 import 'package:analyzer/src/generated/migration.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 
@@ -46,12 +44,15 @@
   /// For example given the type `class C<T> { C(T arg); }`, the generic
   /// function type is `<T>(T) -> C<T>`.
   FunctionType get asType {
-    return FunctionTypeImpl(
-      typeFormals: typeParameters,
-      parameters: element.parameters,
-      returnType: element.returnType,
-      nullabilitySuffix: NullabilitySuffix.none,
-    );
+    var typeParameters = this.typeParameters;
+    return typeParameters.isEmpty
+        ? element.type
+        : FunctionTypeImpl(
+            typeFormals: typeParameters,
+            parameters: element.parameters,
+            returnType: element.returnType,
+            nullabilitySuffix: NullabilitySuffix.none,
+          );
   }
 }
 
@@ -62,9 +63,6 @@
   final MigrationResolutionHooks? _migrationResolutionHooks;
   final bool _genericMetadataIsEnabled;
 
-  List<DartType>? _typeArgumentTypes;
-  FunctionType? _invokeType;
-
   InvocationInferenceHelper({
     required ResolverVisitor resolver,
     required ErrorReporter errorReporter,
@@ -77,16 +75,6 @@
         _genericMetadataIsEnabled = resolver.definingLibrary.featureSet
             .isEnabled(Feature.generic_metadata);
 
-  /// Compute the return type of the method or function represented by the given
-  /// type that is being invoked.
-  DartType computeInvokeReturnType(DartType? type) {
-    if (type is FunctionType) {
-      return type.returnType;
-    } else {
-      return DynamicTypeImpl.instance;
-    }
-  }
-
   /// If the constructor referenced by the [constructorName] is generic,
   /// and the [constructorName] does not have explicit type arguments,
   /// return the element and type parameters to infer. Otherwise return `null`.
@@ -94,159 +82,44 @@
     required ConstructorName constructorName,
     required LibraryElement definingLibrary,
   }) {
-    List<TypeParameterElement>? typeParameters;
+    List<TypeParameterElement> typeParameters;
     ConstructorElement? rawElement;
 
     var typeName = constructorName.type;
-    var typeArguments = typeName.typeArguments;
     var typeElement = typeName.name.staticElement;
     if (typeElement is ClassElement) {
       typeParameters = typeElement.typeParameters;
-      if (typeParameters.isNotEmpty && typeArguments == null) {
-        var constructorIdentifier = constructorName.name;
-        if (constructorIdentifier == null) {
-          rawElement = typeElement.unnamedConstructor;
-        } else {
-          var name = constructorIdentifier.name;
-          rawElement = typeElement.getNamedConstructor(name);
-          if (rawElement != null &&
-              !rawElement.isAccessibleIn(definingLibrary)) {
-            rawElement = null;
-          }
+      var constructorIdentifier = constructorName.name;
+      if (constructorIdentifier == null) {
+        rawElement = typeElement.unnamedConstructor;
+      } else {
+        var name = constructorIdentifier.name;
+        rawElement = typeElement.getNamedConstructor(name);
+        if (rawElement != null && !rawElement.isAccessibleIn(definingLibrary)) {
+          rawElement = null;
         }
       }
     } else if (typeElement is TypeAliasElement) {
       typeParameters = typeElement.typeParameters;
       var aliasedType = typeElement.aliasedType;
       if (aliasedType is InterfaceType) {
-        if (typeParameters.isNotEmpty && typeArguments == null) {
-          var constructorIdentifier = constructorName.name;
-          rawElement = aliasedType.lookUpConstructor(
-            constructorIdentifier?.name,
-            definingLibrary,
-          );
-        }
+        var constructorIdentifier = constructorName.name;
+        rawElement = aliasedType.lookUpConstructor(
+          constructorIdentifier?.name,
+          definingLibrary,
+        );
       }
+    } else {
+      return null;
     }
 
-    if (typeParameters == null || rawElement == null) {
+    if (rawElement == null) {
       return null;
     }
     rawElement = _resolver.toLegacyElement(rawElement);
     return ConstructorElementToInfer(typeParameters, rawElement);
   }
 
-  FunctionType? inferArgumentTypesForGeneric(AstNode inferenceNode,
-      DartType? uninstantiatedType, TypeArgumentList? typeArguments,
-      {AstNode? errorNode,
-      bool isConst = false,
-      required DartType? contextReturnType}) {
-    errorNode ??= inferenceNode;
-    uninstantiatedType = _getFreshType(uninstantiatedType);
-    if (typeArguments == null &&
-        uninstantiatedType is FunctionType &&
-        uninstantiatedType.typeFormals.isNotEmpty) {
-      var typeArguments = _typeSystem.inferGenericFunctionOrType(
-        typeParameters: uninstantiatedType.typeFormals,
-        parameters: const <ParameterElement>[],
-        declaredReturnType: uninstantiatedType.returnType,
-        argumentTypes: const <DartType>[],
-        contextReturnType: contextReturnType,
-        downwards: true,
-        isConst: isConst,
-        errorReporter: _errorReporter,
-        errorNode: errorNode,
-        genericMetadataIsEnabled: _genericMetadataIsEnabled,
-      );
-      if (typeArguments != null) {
-        return uninstantiatedType.instantiate(typeArguments);
-      }
-    }
-    return null;
-  }
-
-  DartType? inferArgumentTypesForInvocation(
-      InvocationExpression node, DartType? type,
-      {required DartType? contextType}) {
-    return inferArgumentTypesForGeneric(node, type, node.typeArguments,
-            contextReturnType: contextType) ??
-        node.staticInvokeType;
-  }
-
-  /// Given a possibly generic invocation like `o.m(args)` or `(f)(args)` try to
-  /// infer the instantiated generic function type.
-  ///
-  /// This takes into account both the context type, as well as information from
-  /// the argument types.
-  void inferGenericInvocationExpression(
-      InvocationExpressionImpl node, DartType? type,
-      {required DartType? contextType}) {
-    var arguments = node.argumentList;
-    var freshType = _getFreshType(type);
-
-    var inferred = inferGenericInvoke(
-        node, freshType, node.typeArguments, arguments, node.function,
-        contextReturnType: contextType);
-    if (inferred != null && inferred != node.staticInvokeType) {
-      // Fix up the parameter elements based on inferred method.
-      arguments.correspondingStaticParameters =
-          ResolverVisitor.resolveArgumentsToParameters(
-        argumentList: arguments,
-        parameters: inferred.parameters,
-      );
-      node.staticInvokeType = inferred;
-    }
-  }
-
-  /// Given a possibly generic invocation or instance creation, such as
-  /// `o.m(args)` or `(f)(args)` or `new T(args)` try to infer the instantiated
-  /// generic function type.
-  ///
-  /// This takes into account both the context type, as well as information from
-  /// the argument types.
-  FunctionType? inferGenericInvoke(
-      AstNode node,
-      DartType? fnType,
-      TypeArgumentList? typeArguments,
-      ArgumentList argumentList,
-      AstNode errorNode,
-      {bool isConst = false,
-      required DartType? contextReturnType}) {
-    if (typeArguments == null &&
-        fnType is FunctionType &&
-        fnType.typeFormals.isNotEmpty) {
-      // Get the parameters that correspond to the uninstantiated generic.
-      var typeArgs = _inferUpwards(
-        rawType: fnType,
-        argumentList: argumentList,
-        contextType: contextReturnType,
-        isConst: isConst,
-        errorNode: errorNode,
-      );
-      if (node is InvocationExpressionImpl) {
-        node.typeArgumentTypes = typeArgs;
-      }
-      if (typeArgs != null) {
-        return fnType.instantiate(typeArgs);
-      }
-      return fnType;
-    }
-
-    // There is currently no other place where we set type arguments
-    // for FunctionExpressionInvocation(s), so set it here, if not inferred.
-    if (node is FunctionExpressionInvocationImpl) {
-      if (typeArguments != null) {
-        var typeArgs =
-            typeArguments.arguments.map((n) => n.typeOrThrow).toList();
-        node.typeArgumentTypes = typeArgs;
-      } else {
-        node.typeArgumentTypes = const <DartType>[];
-      }
-    }
-
-    return null;
-  }
-
   /// Given an uninstantiated generic function type, referenced by the
   /// [identifier] in the tear-off [expression], try to infer the instantiated
   /// generic function type from the surrounding context.
@@ -286,31 +159,6 @@
     }
   }
 
-  /// Finish resolution of the [FunctionExpressionInvocation].
-  ///
-  /// We have already found the invoked [ExecutableElement], and the [rawType]
-  /// is its not yet instantiated type. Here we perform downwards inference,
-  /// resolution of arguments, and upwards inference.
-  void resolveFunctionExpressionInvocation({
-    required FunctionExpressionInvocationImpl node,
-    required FunctionType rawType,
-    required List<WhyNotPromotedGetter> whyNotPromotedList,
-    required DartType? contextType,
-  }) {
-    _resolveInvocation(
-      rawType: rawType,
-      typeArgumentList: node.typeArguments,
-      argumentList: node.argumentList,
-      contextType: contextType,
-      isConst: false,
-      errorNode: node.function,
-      whyNotPromotedList: whyNotPromotedList,
-    );
-
-    node.typeArgumentTypes = _typeArgumentTypes;
-    node.staticInvokeType = _invokeType;
-  }
-
   /// Finish resolution of the [MethodInvocation].
   ///
   /// We have already found the invoked [ExecutableElement], and the [rawType]
@@ -322,245 +170,14 @@
     required List<WhyNotPromotedGetter> whyNotPromotedList,
     required DartType? contextType,
   }) {
-    _resolveInvocation(
+    var returnType = MethodInvocationInferrer.forNode(node).resolveInvocation(
+      resolver: _resolver,
+      node: node,
       rawType: rawType,
-      typeArgumentList: node.typeArguments,
-      argumentList: node.argumentList,
       contextType: contextType,
-      isConst: false,
-      errorNode: node.function,
       whyNotPromotedList: whyNotPromotedList,
     );
 
-    node.typeArgumentTypes = _typeArgumentTypes;
-    node.staticInvokeType = _invokeType;
-
-    var returnType = computeInvokeReturnType(_invokeType);
-    var targetType = node.realTarget?.staticType;
-    if (targetType != null) {
-      returnType = _typeSystem.refineNumericInvocationType(
-        targetType,
-        node.methodName.staticElement,
-        [
-          for (var argument in node.argumentList.arguments) argument.typeOrThrow
-        ],
-        returnType,
-      );
-    }
     recordStaticType(node, returnType, contextType: contextType);
   }
-
-  List<DartType>? _inferDownwards({
-    required FunctionType rawType,
-    required DartType? contextType,
-    required bool isConst,
-    required AstNode errorNode,
-  }) {
-    return _typeSystem.inferGenericFunctionOrType(
-      typeParameters: rawType.typeFormals,
-      parameters: const <ParameterElement>[],
-      declaredReturnType: rawType.returnType,
-      argumentTypes: const <DartType>[],
-      contextReturnType: contextType,
-      downwards: true,
-      isConst: isConst,
-      errorReporter: _errorReporter,
-      errorNode: errorNode,
-      genericMetadataIsEnabled: _genericMetadataIsEnabled,
-    );
-  }
-
-  /// TODO(scheglov) Instead of [isConst] sanitize [contextType] before calling.
-  List<DartType>? _inferUpwards({
-    required FunctionType rawType,
-    required DartType? contextType,
-    required ArgumentList argumentList,
-    required bool isConst,
-    required AstNode errorNode,
-  }) {
-    rawType = _getFreshType(rawType) as FunctionType;
-
-    // Get the parameters that correspond to the uninstantiated generic.
-    List<ParameterElement?> rawParameters =
-        ResolverVisitor.resolveArgumentsToParameters(
-      argumentList: argumentList,
-      parameters: rawType.parameters,
-    );
-
-    List<ParameterElement> params = <ParameterElement>[];
-    List<DartType> argTypes = <DartType>[];
-    for (int i = 0, length = rawParameters.length; i < length; i++) {
-      ParameterElement? parameter = rawParameters[i];
-      if (parameter != null) {
-        params.add(parameter);
-        argTypes.add(argumentList.arguments[i].typeOrThrow);
-      }
-    }
-    var typeArgs = _typeSystem.inferGenericFunctionOrType(
-      typeParameters: rawType.typeFormals,
-      parameters: params,
-      declaredReturnType: rawType.returnType,
-      argumentTypes: argTypes,
-      contextReturnType: contextType,
-      isConst: isConst,
-      errorReporter: _errorReporter,
-      errorNode: errorNode,
-      genericMetadataIsEnabled: _genericMetadataIsEnabled,
-    );
-    return typeArgs;
-  }
-
-  bool _isCallToIdentical(AstNode? invocation) {
-    if (invocation is MethodInvocation) {
-      var invokedMethod = invocation.methodName.staticElement;
-      return invokedMethod != null &&
-          invokedMethod.name == 'identical' &&
-          invokedMethod.library!.isDartCore;
-    }
-    return false;
-  }
-
-  void _resolveArguments(
-      ArgumentList argumentList,
-      List<WhyNotPromotedGetter> whyNotPromotedList,
-      List<ParameterElement> parameters,
-      {required DartType? methodInvocationContext}) {
-    _resolver.analyzeArgumentList(argumentList, parameters,
-        isIdentical: _isCallToIdentical(argumentList.parent),
-        whyNotPromotedList: whyNotPromotedList,
-        methodInvocationContext: methodInvocationContext);
-  }
-
-  void _resolveInvocation({
-    required FunctionType rawType,
-    required DartType? contextType,
-    required TypeArgumentList? typeArgumentList,
-    required ArgumentListImpl argumentList,
-    required bool isConst,
-    required AstNode errorNode,
-    required List<WhyNotPromotedGetter> whyNotPromotedList,
-  }) {
-    if (typeArgumentList != null) {
-      _resolveInvocationWithTypeArguments(
-        rawType: rawType,
-        typeArgumentList: typeArgumentList,
-        argumentList: argumentList,
-        whyNotPromotedList: whyNotPromotedList,
-        methodInvocationContext: contextType,
-      );
-    } else {
-      _resolveInvocationWithoutTypeArguments(
-        rawType: rawType,
-        contextType: contextType,
-        argumentList: argumentList,
-        isConst: isConst,
-        errorNode: errorNode,
-        whyNotPromotedList: whyNotPromotedList,
-      );
-    }
-    _setCorrespondingParameters(argumentList, _invokeType!);
-  }
-
-  void _resolveInvocationWithoutTypeArguments({
-    required FunctionType rawType,
-    required DartType? contextType,
-    required ArgumentList argumentList,
-    required bool isConst,
-    required AstNode errorNode,
-    required List<WhyNotPromotedGetter> whyNotPromotedList,
-  }) {
-    var typeParameters = rawType.typeFormals;
-
-    if (typeParameters.isEmpty) {
-      _resolveArguments(argumentList, whyNotPromotedList, rawType.parameters,
-          methodInvocationContext: contextType);
-
-      _typeArgumentTypes = const <DartType>[];
-      _invokeType = rawType;
-    } else {
-      rawType = _getFreshType(rawType) as FunctionType;
-
-      var downwardsTypeArguments = _inferDownwards(
-        rawType: rawType,
-        contextType: contextType,
-        isConst: isConst,
-        errorNode: errorNode,
-      )!;
-
-      var downwardsInvokeType = rawType.instantiate(downwardsTypeArguments);
-
-      _resolveArguments(
-          argumentList, whyNotPromotedList, downwardsInvokeType.parameters,
-          methodInvocationContext: contextType);
-
-      _typeArgumentTypes = _inferUpwards(
-        rawType: rawType,
-        argumentList: argumentList,
-        contextType: contextType,
-        isConst: isConst,
-        errorNode: errorNode,
-      );
-      _invokeType = rawType.instantiate(_typeArgumentTypes!);
-    }
-  }
-
-  void _resolveInvocationWithTypeArguments({
-    required FunctionType rawType,
-    required TypeArgumentList typeArgumentList,
-    required ArgumentList argumentList,
-    required List<WhyNotPromotedGetter> whyNotPromotedList,
-    required DartType? methodInvocationContext,
-  }) {
-    var typeParameters = rawType.typeFormals;
-
-    List<DartType> typeArguments;
-    if (typeArgumentList.arguments.length != typeParameters.length) {
-      _errorReporter.reportErrorForNode(
-        CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD,
-        typeArgumentList,
-        [
-          rawType,
-          typeParameters.length,
-          typeArgumentList.arguments.length,
-        ],
-      );
-      typeArguments = List.filled(
-        typeParameters.length,
-        DynamicTypeImpl.instance,
-      );
-    } else {
-      typeArguments = typeArgumentList.arguments
-          .map((typeArgument) => typeArgument.typeOrThrow)
-          .toList(growable: true);
-    }
-
-    var invokeType = rawType.instantiate(typeArguments);
-
-    _resolveArguments(argumentList, whyNotPromotedList, invokeType.parameters,
-        methodInvocationContext: methodInvocationContext);
-
-    _typeArgumentTypes = typeArguments;
-    _invokeType = invokeType;
-  }
-
-  void _setCorrespondingParameters(
-    ArgumentListImpl argumentList,
-    FunctionType invokeType,
-  ) {
-    var parameters = ResolverVisitor.resolveArgumentsToParameters(
-      argumentList: argumentList,
-      parameters: invokeType.parameters,
-      errorReporter: _errorReporter,
-    );
-    argumentList.correspondingStaticParameters = parameters;
-  }
-
-  static DartType? _getFreshType(DartType? type) {
-    if (type is FunctionType) {
-      var parameters = getFreshTypeParameters(type.typeFormals);
-      return parameters.applyToFunctionType(type);
-    } else {
-      return type;
-    }
-  }
 }
diff --git a/pkg/analyzer/lib/src/dart/resolver/invocation_inferrer.dart b/pkg/analyzer/lib/src/dart/resolver/invocation_inferrer.dart
new file mode 100644
index 0000000..c40a4ff
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/resolver/invocation_inferrer.dart
@@ -0,0 +1,545 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:_fe_analyzer_shared/src/base/errors.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/extensions.dart';
+import 'package:analyzer/src/dart/element/member.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type_algebra.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+
+/// Specialization of [InvocationInferrer] for performing type inference on AST
+/// nodes of type [Annotation] that resolve to a constructor invocation.
+class AnnotationInferrer extends FullInvocationInferrer<AnnotationImpl> {
+  /// The identifier pointing to the constructor that's being invoked, or `null`
+  /// if a constructor name couldn't be found (should only happen when
+  /// recovering from errors).  If the constructor is generic, this identifier's
+  /// static element will be updated to point to a [ConstructorMember] with type
+  /// arguments filled in.
+  final SimpleIdentifierImpl? constructorName;
+
+  AnnotationInferrer({required this.constructorName}) : super._();
+
+  @override
+  bool get _needsTypeArgumentBoundsCheck => true;
+
+  @override
+  ErrorCode get _wrongNumberOfTypeArgumentsErrorCode =>
+      CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS;
+
+  @override
+  ArgumentListImpl _getArgumentList(AnnotationImpl node) => node.arguments!;
+
+  @override
+  bool _getIsConst(AnnotationImpl node) => true;
+
+  @override
+  TypeArgumentListImpl? _getTypeArguments(AnnotationImpl node) =>
+      node.typeArguments;
+
+  @override
+  bool _isGenericInferenceDisabled(ResolverVisitor resolver) =>
+      !resolver.genericMetadataIsEnabled;
+
+  @override
+  List<ParameterElement>? _storeResult(AnnotationImpl node,
+      List<DartType>? typeArgumentTypes, FunctionType? invokeType) {
+    if (invokeType != null) {
+      var constructorElement = ConstructorMember.from(
+        node.element as ConstructorElement,
+        invokeType.returnType as InterfaceType,
+      );
+      constructorName?.staticElement = constructorElement;
+      node.element = constructorElement;
+      return constructorElement.parameters;
+    }
+    return null;
+  }
+}
+
+/// Specialization of [InvocationInferrer] for performing type inference on AST
+/// nodes of type [ExtensionOverride].
+class ExtensionOverrideInferrer
+    extends InvocationInferrer<ExtensionOverrideImpl> {
+  const ExtensionOverrideInferrer() : super._();
+
+  @override
+  ArgumentListImpl _getArgumentList(ExtensionOverrideImpl node) =>
+      node.argumentList;
+}
+
+/// Specialization of [InvocationInferrer] for performing type inference on AST
+/// nodes that require full downward and upward inference.
+abstract class FullInvocationInferrer<Node extends AstNodeImpl>
+    extends InvocationInferrer<Node> {
+  const FullInvocationInferrer._() : super._();
+
+  bool get _needsTypeArgumentBoundsCheck => false;
+
+  ErrorCode get _wrongNumberOfTypeArgumentsErrorCode =>
+      CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD;
+
+  @override
+  DartType resolveInvocation({
+    required ResolverVisitor resolver,
+    required Node node,
+    required FunctionType? rawType,
+    required DartType? contextType,
+    required List<WhyNotPromotedGetter> whyNotPromotedList,
+  }) {
+    var typeArgumentList = _getTypeArguments(node);
+
+    List<DartType>? typeArgumentTypes;
+    FunctionType? invokeType;
+    if (_isGenericInferenceDisabled(resolver)) {
+      if (rawType != null && rawType.typeFormals.isNotEmpty) {
+        typeArgumentTypes = List.filled(
+          rawType.typeFormals.length,
+          DynamicTypeImpl.instance,
+        );
+      } else {
+        typeArgumentTypes = const <DartType>[];
+        invokeType = rawType;
+      }
+
+      invokeType = rawType?.instantiate(typeArgumentTypes);
+    } else if (typeArgumentList != null) {
+      if (rawType != null &&
+          typeArgumentList.arguments.length != rawType.typeFormals.length) {
+        var typeParameters = rawType.typeFormals;
+        _reportWrongNumberOfTypeArguments(
+            resolver, typeArgumentList, rawType, typeParameters);
+        typeArgumentTypes = List.filled(
+          typeParameters.length,
+          DynamicTypeImpl.instance,
+        );
+      } else {
+        typeArgumentTypes = typeArgumentList.arguments
+            .map((typeArgument) => typeArgument.typeOrThrow)
+            .toList(growable: true);
+        if (rawType != null && _needsTypeArgumentBoundsCheck) {
+          var typeParameters = rawType.typeFormals;
+          var substitution = Substitution.fromPairs(
+            typeParameters,
+            typeArgumentTypes,
+          );
+          for (var i = 0; i < typeParameters.length; i++) {
+            var typeParameter = typeParameters[i];
+            var bound = typeParameter.bound;
+            if (bound != null) {
+              bound = resolver.definingLibrary.toLegacyTypeIfOptOut(bound);
+              bound = substitution.substituteType(bound);
+              var typeArgument = typeArgumentTypes[i];
+              if (!resolver.typeSystem.isSubtypeOf(typeArgument, bound)) {
+                resolver.errorReporter.reportErrorForNode(
+                  CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
+                  typeArgumentList.arguments[i],
+                  [typeArgument, typeParameter.name, bound],
+                );
+              }
+            }
+          }
+        }
+      }
+
+      invokeType = rawType?.instantiate(typeArgumentTypes);
+    } else if (rawType == null || rawType.typeFormals.isEmpty) {
+      typeArgumentTypes = const <DartType>[];
+      invokeType = rawType;
+    } else {
+      rawType = getFreshTypeParameters(rawType.typeFormals)
+          .applyToFunctionType(rawType);
+
+      var downwardsTypeArguments =
+          resolver.typeSystem.inferGenericFunctionOrType(
+        typeParameters: rawType.typeFormals,
+        parameters: const <ParameterElement>[],
+        declaredReturnType: rawType.returnType,
+        argumentTypes: const <DartType>[],
+        contextReturnType: contextType,
+        downwards: true,
+        isConst: _getIsConst(node),
+        errorReporter: resolver.errorReporter,
+        errorNode: _getErrorNode(node),
+        genericMetadataIsEnabled: resolver.genericMetadataIsEnabled,
+      )!;
+
+      invokeType = rawType.instantiate(downwardsTypeArguments);
+    }
+
+    super.resolveInvocation(
+        resolver: resolver,
+        node: node,
+        rawType: invokeType,
+        contextType: contextType,
+        whyNotPromotedList: whyNotPromotedList);
+
+    var argumentList = _getArgumentList(node);
+
+    if (typeArgumentTypes == null) {
+      if (rawType != null) {
+        // Get the parameters that correspond to the uninstantiated generic.
+        List<ParameterElement?> rawParameters =
+            ResolverVisitor.resolveArgumentsToParameters(
+          argumentList: argumentList,
+          parameters: rawType.parameters,
+        );
+
+        List<ParameterElement> params = <ParameterElement>[];
+        List<DartType> argTypes = <DartType>[];
+        for (int i = 0, length = rawParameters.length; i < length; i++) {
+          ParameterElement? parameter = rawParameters[i];
+          if (parameter != null) {
+            params.add(parameter);
+            argTypes.add(argumentList.arguments[i].typeOrThrow);
+          }
+        }
+        typeArgumentTypes = resolver.typeSystem.inferGenericFunctionOrType(
+          typeParameters: rawType.typeFormals,
+          parameters: params,
+          declaredReturnType: rawType.returnType,
+          argumentTypes: argTypes,
+          contextReturnType: contextType,
+          isConst: _getIsConst(node),
+          errorReporter: resolver.errorReporter,
+          errorNode: _getErrorNode(node),
+          genericMetadataIsEnabled: resolver.genericMetadataIsEnabled,
+        )!;
+        invokeType = rawType.instantiate(typeArgumentTypes);
+      } else {
+        typeArgumentTypes = const [];
+      }
+    }
+
+    var parameters = _storeResult(node, typeArgumentTypes, invokeType);
+    if (parameters != null) {
+      argumentList.correspondingStaticParameters =
+          ResolverVisitor.resolveArgumentsToParameters(
+        argumentList: argumentList,
+        parameters: parameters,
+        errorReporter: resolver.errorReporter,
+      );
+    }
+    var returnType = InvocationInferrer.computeInvokeReturnType(invokeType);
+    return _refineReturnType(resolver, node, returnType);
+  }
+
+  AstNode _getErrorNode(Node node) => node;
+
+  bool _getIsConst(Node node) => false;
+
+  TypeArgumentListImpl? _getTypeArguments(Node node);
+
+  bool _isGenericInferenceDisabled(ResolverVisitor resolver) => false;
+
+  DartType _refineReturnType(
+          ResolverVisitor resolver, Node node, DartType returnType) =>
+      returnType;
+
+  void _reportWrongNumberOfTypeArguments(
+      ResolverVisitor resolver,
+      TypeArgumentList typeArgumentList,
+      FunctionType rawType,
+      List<TypeParameterElement> typeParameters) {
+    resolver.errorReporter.reportErrorForNode(
+      _wrongNumberOfTypeArgumentsErrorCode,
+      typeArgumentList,
+      [
+        rawType,
+        typeParameters.length,
+        typeArgumentList.arguments.length,
+      ],
+    );
+  }
+
+  List<ParameterElement>? _storeResult(
+      Node node, List<DartType>? typeArgumentTypes, FunctionType? invokeType) {
+    return invokeType?.parameters;
+  }
+}
+
+/// Specialization of [InvocationInferrer] for performing type inference on AST
+/// nodes of type [FunctionExpressionInvocation].
+class FunctionExpressionInvocationInferrer
+    extends InvocationExpressionInferrer<FunctionExpressionInvocationImpl> {
+  const FunctionExpressionInvocationInferrer() : super._();
+
+  @override
+  ExpressionImpl _getErrorNode(FunctionExpressionInvocationImpl node) =>
+      node.function;
+}
+
+/// Specialization of [InvocationInferrer] for performing type inference on AST
+/// nodes of type [InstanceCreationExpression].
+class InstanceCreationInferrer
+    extends FullInvocationInferrer<InstanceCreationExpressionImpl> {
+  const InstanceCreationInferrer() : super._();
+
+  @override
+  bool get _needsTypeArgumentBoundsCheck => true;
+
+  @override
+  ArgumentListImpl _getArgumentList(InstanceCreationExpressionImpl node) =>
+      node.argumentList;
+
+  @override
+  ConstructorNameImpl _getErrorNode(InstanceCreationExpressionImpl node) =>
+      node.constructorName;
+
+  @override
+  bool _getIsConst(InstanceCreationExpressionImpl node) => node.isConst;
+
+  @override
+  TypeArgumentListImpl? _getTypeArguments(InstanceCreationExpressionImpl node) {
+    // For an instance creation expression the type arguments are on the
+    // constructor name.
+    return node.constructorName.type.typeArguments;
+  }
+
+  @override
+  void _reportWrongNumberOfTypeArguments(
+      ResolverVisitor resolver,
+      TypeArgumentList typeArgumentList,
+      FunctionType rawType,
+      List<TypeParameterElement> typeParameters) {
+    // Error reporting for instance creations is done elsewhere.
+  }
+
+  @override
+  List<ParameterElement>? _storeResult(InstanceCreationExpressionImpl node,
+      List<DartType>? typeArgumentTypes, FunctionType? invokeType) {
+    if (invokeType != null) {
+      var constructedType = invokeType.returnType;
+      node.constructorName.type.type = constructedType;
+      var constructorElement = ConstructorMember.from(
+        node.constructorName.staticElement!,
+        constructedType as InterfaceType,
+      );
+      node.constructorName.staticElement = constructorElement;
+      return constructorElement.parameters;
+    }
+    return null;
+  }
+}
+
+/// Specialization of [InvocationInferrer] for performing type inference on AST
+/// nodes derived from [InvocationExpression].
+abstract class InvocationExpressionInferrer<
+        Node extends InvocationExpressionImpl>
+    extends FullInvocationInferrer<Node> {
+  const InvocationExpressionInferrer._() : super._();
+
+  @override
+  ArgumentListImpl _getArgumentList(Node node) => node.argumentList;
+
+  @override
+  Expression _getErrorNode(Node node) => node.function;
+
+  @override
+  TypeArgumentListImpl? _getTypeArguments(Node node) => node.typeArguments;
+
+  @override
+  List<ParameterElement>? _storeResult(
+      Node node, List<DartType>? typeArgumentTypes, FunctionType? invokeType) {
+    node.typeArgumentTypes = typeArgumentTypes;
+    node.staticInvokeType = invokeType ?? DynamicTypeImpl.instance;
+    return super._storeResult(node, typeArgumentTypes, invokeType);
+  }
+}
+
+/// Base class containing functionality for performing type inference on AST
+/// nodes that invoke a method, function, or constructor.
+abstract class InvocationInferrer<Node extends AstNodeImpl> {
+  const InvocationInferrer._();
+
+  /// Performs type inference on an invocation expression of type [Node].
+  /// [rawType] should be the type of the function the invocation is resolved to
+  /// (with type arguments not applied yet).
+  void resolveInvocation({
+    required ResolverVisitor resolver,
+    required Node node,
+    required FunctionType? rawType,
+    required DartType? contextType,
+    required List<WhyNotPromotedGetter> whyNotPromotedList,
+  }) {
+    var parameters = rawType?.parameters;
+    var namedParameters = <String, ParameterElement>{};
+    if (parameters != null) {
+      for (var i = 0; i < parameters.length; i++) {
+        var parameter = parameters[i];
+        if (parameter.isNamed) {
+          namedParameters[parameter.name] = parameter;
+        }
+      }
+    }
+    var argumentList = _getArgumentList(node);
+    resolver.checkUnreachableNode(argumentList);
+    var flow = resolver.flowAnalysis.flow;
+    var positionalParameterIndex = 0;
+    for (var argument in _iterateArguments(resolver, argumentList)) {
+      ParameterElement? parameter;
+      if (argument is NamedExpression) {
+        parameter = namedParameters[argument.name.label.name];
+      } else if (parameters != null) {
+        while (positionalParameterIndex < parameters.length) {
+          parameter = parameters[positionalParameterIndex++];
+          if (!parameter.isNamed) {
+            break;
+          }
+        }
+      }
+      DartType? parameterContextType;
+      if (parameter != null) {
+        var parameterType = parameter.type;
+        parameterContextType = _computeContextForArgument(
+            resolver, node, parameterType, contextType);
+      }
+      resolver.analyzeExpression(argument, parameterContextType);
+      if (flow != null) {
+        whyNotPromotedList.add(flow.whyNotPromoted(argument));
+      }
+    }
+  }
+
+  /// Computes the type context that should be used when evaluating a particular
+  /// argument of the invocation.  Usually this is just the type of the
+  /// corresponding parameter, but it can be different for certain primitive
+  /// numeric operations.
+  DartType? _computeContextForArgument(ResolverVisitor resolver, Node node,
+          DartType parameterType, DartType? methodInvocationContext) =>
+      parameterType;
+
+  /// Gets the argument list for the invocation.  TODO(paulberry): remove?
+  ArgumentListImpl _getArgumentList(Node node);
+
+  /// Iterates through the argument list for the invocation.  Usually this is
+  /// just a simple iteration through the arguments, but in certain cases, some
+  /// flow analysis methods need to be called in between visiting the various
+  /// arguments.
+  Iterable<Expression> _iterateArguments(
+          ResolverVisitor resolver, ArgumentList argumentList) =>
+      argumentList.arguments;
+
+  /// Computes the return type of the method or function represented by the
+  /// given type that is being invoked.
+  static DartType computeInvokeReturnType(DartType? type) {
+    if (type is FunctionType) {
+      return type.returnType;
+    } else {
+      return DynamicTypeImpl.instance;
+    }
+  }
+}
+
+/// Specialization of [InvocationInferrer] for performing type inference on AST
+/// nodes of type [MethodInvocation].
+class MethodInvocationInferrer
+    extends InvocationExpressionInferrer<MethodInvocationImpl> {
+  /// Gets the appropriate instance of [MethodInvocation] for the given [node].
+  ///
+  /// This factory takes care of the fact that invocations of `identical` need
+  /// to have special integration with flow analysis.
+  factory MethodInvocationInferrer.forNode(MethodInvocationImpl node) {
+    var invokedMethod = node.methodName.staticElement;
+    if (invokedMethod != null &&
+        invokedMethod.name == 'identical' &&
+        invokedMethod.library!.isDartCore &&
+        node.argumentList.arguments.length == 2) {
+      return const _IdenticalInvocationInferrer._();
+    } else {
+      return const MethodInvocationInferrer._();
+    }
+  }
+
+  const MethodInvocationInferrer._() : super._();
+
+  @override
+  DartType? _computeContextForArgument(
+      ResolverVisitor resolver,
+      MethodInvocationImpl node,
+      DartType parameterType,
+      DartType? methodInvocationContext) {
+    var contextType = super._computeContextForArgument(
+        resolver, node, parameterType, methodInvocationContext);
+    var targetType = node.realTarget?.staticType;
+    if (targetType != null) {
+      contextType = resolver.typeSystem.refineNumericInvocationContext(
+          targetType,
+          node.methodName.staticElement,
+          methodInvocationContext,
+          parameterType);
+    }
+    return contextType;
+  }
+
+  @override
+  DartType _refineReturnType(ResolverVisitor resolver,
+      MethodInvocationImpl node, DartType returnType) {
+    var targetType = node.realTarget?.staticType;
+    if (targetType != null) {
+      returnType = resolver.typeSystem.refineNumericInvocationType(
+        targetType,
+        node.methodName.staticElement,
+        [
+          for (var argument in node.argumentList.arguments) argument.typeOrThrow
+        ],
+        returnType,
+      );
+    }
+    return returnType;
+  }
+}
+
+/// Specialization of [InvocationInferrer] for performing type inference on AST
+/// nodes of type [RedirectingConstructorInvocation].
+class RedirectingConstructorInvocationInferrer
+    extends InvocationInferrer<RedirectingConstructorInvocationImpl> {
+  const RedirectingConstructorInvocationInferrer() : super._();
+
+  @override
+  ArgumentListImpl _getArgumentList(
+          RedirectingConstructorInvocationImpl node) =>
+      node.argumentList;
+}
+
+/// Specialization of [InvocationInferrer] for performing type inference on AST
+/// nodes of type [SuperConstructorInvocation].
+class SuperConstructorInvocationInferrer
+    extends InvocationInferrer<SuperConstructorInvocationImpl> {
+  const SuperConstructorInvocationInferrer() : super._();
+
+  @override
+  ArgumentListImpl _getArgumentList(SuperConstructorInvocationImpl node) =>
+      node.argumentList;
+}
+
+/// Specialization of [InvocationInferrer] for performing type inference on AST
+/// nodes of type [MethodInvocation] that resolve to the core function
+/// `identical`.  (Such nodes need to be handled in a special way due to the
+/// interaction between `identical` and flow analysis).
+class _IdenticalInvocationInferrer extends MethodInvocationInferrer {
+  const _IdenticalInvocationInferrer._() : super._();
+
+  @override
+  Iterable<Expression> _iterateArguments(
+      ResolverVisitor resolver, ArgumentList argumentList) sync* {
+    var flow = resolver.flowAnalysis.flow;
+    var arguments = argumentList.arguments;
+    assert(arguments.length == 2);
+    var firstArg = arguments[0];
+    yield firstArg;
+    firstArg = arguments[0]; // In case it was rewritten
+    flow?.equalityOp_rightBegin(firstArg, firstArg.typeOrThrow);
+    var secondArg = arguments[1];
+    yield secondArg;
+    secondArg = arguments[1]; // In case it was rewritten
+    flow?.equalityOp_end(
+        argumentList.parent as Expression, secondArg, secondArg.typeOrThrow);
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
index 0cc6306..724f3c1 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -15,6 +15,7 @@
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
 import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
+import 'package:analyzer/src/dart/resolver/invocation_inferrer.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/migratable_ast_info_provider.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -323,38 +324,17 @@
     );
   }
 
-  /// [InvocationExpression.staticInvokeType] has been set for the [node].
-  /// Use it to set context for arguments, and resolve them.
-  void _resolveArguments(
-      MethodInvocationImpl node, List<WhyNotPromotedGetter> whyNotPromotedList,
-      {required DartType? contextType}) {
-    // TODO(scheglov) This is bad, don't write raw type, carry it
-    var callerType = _inferenceHelper.inferArgumentTypesForInvocation(
-      node,
-      node.methodName.staticType,
-      contextType: contextType,
-    );
-    _resolver.analyzeArgumentList(node.argumentList,
-        callerType is FunctionType ? callerType.parameters : null,
-        whyNotPromotedList: whyNotPromotedList,
-        methodInvocationContext: contextType);
-  }
-
   void _resolveArguments_finishInference(
       MethodInvocationImpl node, List<WhyNotPromotedGetter> whyNotPromotedList,
       {required DartType? contextType}) {
-    _resolveArguments(node, whyNotPromotedList, contextType: contextType);
-
-    // TODO(scheglov) This is bad, don't put / get raw FunctionType this way.
-    _inferenceHelper.inferGenericInvocationExpression(
-      node,
-      node.methodName.staticType,
-      contextType: contextType,
-    );
-
-    DartType staticStaticType = _inferenceHelper.computeInvokeReturnType(
-      node.staticInvokeType,
-    );
+    var methodInvocationInferrer = MethodInvocationInferrer.forNode(node);
+    var rawType = node.methodName.staticType;
+    DartType staticStaticType = methodInvocationInferrer.resolveInvocation(
+        resolver: _resolver,
+        node: node,
+        rawType: rawType is FunctionType ? rawType : null,
+        contextType: contextType,
+        whyNotPromotedList: whyNotPromotedList);
     _inferenceHelper.recordStaticType(node, staticStaticType,
         contextType: contextType);
   }
@@ -473,29 +453,32 @@
     var objectElement = _typeSystem.typeProvider.objectElement;
     var target = objectElement.getMethod(nameNode.name);
 
-    var hasMatchingObjectMethod = false;
+    FunctionType? rawType;
     if (target is MethodElement && !target.isStatic) {
       var arguments = node.argumentList.arguments;
-      hasMatchingObjectMethod = arguments.length == target.parameters.length &&
-          !arguments.any((e) => e is NamedExpression);
+      var hasMatchingObjectMethod =
+          arguments.length == target.parameters.length &&
+              !arguments.any((e) => e is NamedExpression);
       if (hasMatchingObjectMethod) {
         target = _resolver.toLegacyElement(target);
         nameNode.staticElement = target;
-        node.staticInvokeType = target.type;
+        rawType = target.type;
         node.staticType = target.returnType;
       }
     }
 
-    if (!hasMatchingObjectMethod) {
+    if (rawType == null) {
       nameNode.staticType = DynamicTypeImpl.instance;
-      node.staticInvokeType = DynamicTypeImpl.instance;
       node.staticType = DynamicTypeImpl.instance;
     }
 
     _setExplicitTypeArgumentTypes();
-    _resolver.analyzeArgumentList(node.argumentList, null,
+    MethodInvocationInferrer.forNode(node).resolveInvocation(
+        resolver: _resolver,
+        node: node,
+        rawType: rawType,
         whyNotPromotedList: whyNotPromotedList,
-        methodInvocationContext: contextType);
+        contextType: contextType);
   }
 
   void _resolveReceiverFunctionBounded(
@@ -563,7 +546,12 @@
       node.staticInvokeType = _dynamicType;
       node.staticType = NeverTypeImpl.instance;
 
-      _resolveArguments(node, whyNotPromotedList, contextType: contextType);
+      MethodInvocationInferrer.forNode(node).resolveInvocation(
+          resolver: _resolver,
+          node: node,
+          rawType: null,
+          contextType: contextType,
+          whyNotPromotedList: whyNotPromotedList);
 
       _resolver.errorReporter.reportErrorForNode(
         HintCode.RECEIVER_OF_TYPE_NEVER,
@@ -577,7 +565,12 @@
       node.staticInvokeType = _dynamicType;
       node.staticType = _dynamicType;
 
-      _resolveArguments(node, whyNotPromotedList, contextType: contextType);
+      MethodInvocationInferrer.forNode(node).resolveInvocation(
+          resolver: _resolver,
+          node: node,
+          rawType: null,
+          contextType: contextType,
+          whyNotPromotedList: whyNotPromotedList);
       return;
     }
   }
diff --git a/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
index 4cc71c9..9667c37f 100644
--- a/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
@@ -14,6 +14,7 @@
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
 import 'package:analyzer/src/dart/resolver/assignment_expression_resolver.dart';
 import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
+import 'package:analyzer/src/dart/resolver/invocation_inferrer.dart';
 import 'package:analyzer/src/dart/resolver/type_property_resolver.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -97,11 +98,11 @@
       // We are invoking a getter and then invoking the returned function.
       //
       FunctionType propertyType = element.type;
-      return _resolver.inferenceHelper.computeInvokeReturnType(
+      return InvocationInferrer.computeInvokeReturnType(
         propertyType.returnType,
       );
     } else if (element is ExecutableElement) {
-      return _resolver.inferenceHelper.computeInvokeReturnType(element.type);
+      return InvocationInferrer.computeInvokeReturnType(element.type);
     }
     return DynamicTypeImpl.instance;
   }
diff --git a/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
index 484e305..fc71e4f 100644
--- a/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
@@ -14,6 +14,7 @@
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/dart/resolver/assignment_expression_resolver.dart';
 import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
+import 'package:analyzer/src/dart/resolver/invocation_inferrer.dart';
 import 'package:analyzer/src/dart/resolver/type_property_resolver.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -108,11 +109,11 @@
       // We are invoking a getter and then invoking the returned function.
       //
       var propertyType = element.type;
-      return _resolver.inferenceHelper.computeInvokeReturnType(
+      return InvocationInferrer.computeInvokeReturnType(
         propertyType.returnType,
       );
     } else if (element is ExecutableElement) {
-      return _resolver.inferenceHelper.computeInvokeReturnType(element.type);
+      return InvocationInferrer.computeInvokeReturnType(element.type);
     }
     return DynamicTypeImpl.instance;
   }
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 5d242c3..92f03a7 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -43,6 +43,7 @@
 import 'package:analyzer/src/dart/resolver/function_reference_resolver.dart';
 import 'package:analyzer/src/dart/resolver/instance_creation_expression_resolver.dart';
 import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
+import 'package:analyzer/src/dart/resolver/invocation_inferrer.dart';
 import 'package:analyzer/src/dart/resolver/lexical_lookup.dart';
 import 'package:analyzer/src/dart/resolver/method_invocation_resolver.dart';
 import 'package:analyzer/src/dart/resolver/postfix_expression_resolver.dart';
@@ -248,6 +249,8 @@
 
   late final AnnotationResolver _annotationResolver = AnnotationResolver(this);
 
+  final bool genericMetadataIsEnabled;
+
   /// Initialize a newly created visitor to resolve the nodes in an AST node.
   ///
   /// The [definingLibrary] is the element for the library containing the node
@@ -300,7 +303,9 @@
           isNonNullableByDefault: definingLibrary.isNonNullableByDefault,
         ),
         _featureSet = featureSet,
-        migrationResolutionHooks = migrationResolutionHooks {
+        migrationResolutionHooks = migrationResolutionHooks,
+        genericMetadataIsEnabled =
+            definingLibrary.featureSet.isEnabled(Feature.generic_metadata) {
     var analysisOptions =
         definingLibrary.context.analysisOptions as AnalysisOptionsImpl;
 
@@ -403,73 +408,6 @@
   bool get _isNonNullableByDefault =>
       _featureSet.isEnabled(Feature.non_nullable);
 
-  void analyzeArgumentList(
-      ArgumentList node, List<ParameterElement>? parameters,
-      {bool isIdentical = false,
-      List<WhyNotPromotedGetter>? whyNotPromotedList,
-      DartType? methodInvocationContext}) {
-    whyNotPromotedList ??= [];
-    NodeList<Expression> arguments = node.arguments;
-    var namedParameters = <String, ParameterElement>{};
-    DartType? targetType;
-    Element? methodElement;
-    if (parameters != null) {
-      for (var i = 0; i < parameters.length; i++) {
-        var parameter = parameters[i];
-        if (parameter.isNamed) {
-          namedParameters[parameter.name] = parameter;
-        }
-      }
-
-      var parent = node.parent;
-      if (parent is MethodInvocation) {
-        targetType = parent.realTarget?.staticType;
-        methodElement = parent.methodName.staticElement;
-      }
-    }
-    checkUnreachableNode(node);
-    int length = arguments.length;
-    var flow = flowAnalysis.flow;
-    var positionalParameterIndex = 0;
-    for (var i = 0; i < length; i++) {
-      if (isIdentical && length > 1 && i == 1) {
-        var firstArg = arguments[0];
-        flow?.equalityOp_rightBegin(firstArg, firstArg.typeOrThrow);
-      }
-      var argument = arguments[i];
-      ParameterElement? parameter;
-      if (argument is NamedExpression) {
-        parameter = namedParameters[argument.name.label.name];
-      } else if (parameters != null) {
-        while (positionalParameterIndex < parameters.length) {
-          parameter = parameters[positionalParameterIndex++];
-          if (!parameter.isNamed) {
-            break;
-          }
-        }
-      }
-      DartType? contextType;
-      if (parameter != null) {
-        var parameterType = parameter.type;
-        if (targetType != null) {
-          contextType = typeSystem.refineNumericInvocationContext(targetType,
-              methodElement, methodInvocationContext, parameterType);
-        } else {
-          contextType = parameterType;
-        }
-      }
-      analyzeExpression(argument, contextType);
-      if (flow != null) {
-        whyNotPromotedList.add(flow.whyNotPromoted(arguments[i]));
-      }
-    }
-    if (isIdentical && length > 1) {
-      var secondArg = arguments[1];
-      flow?.equalityOp_end(
-          node.parent as Expression, secondArg, secondArg.typeOrThrow);
-    }
-  }
-
   void analyzeExpression(Expression expression, DartType? contextType) {
     if (contextType != null && contextType.isDynamic) {
       contextType = null;
@@ -1042,12 +980,6 @@
   }
 
   @override
-  void visitArgumentList(ArgumentList node) {
-    assert(false, 'analyzeArgumentList should be used instead');
-    analyzeArgumentList(node, null);
-  }
-
-  @override
   void visitAsExpression(AsExpression node, {DartType? contextType}) {
     checkUnreachableNode(node);
     node.visitChildren(this);
@@ -1600,21 +1532,28 @@
   }
 
   @override
-  void visitExtensionOverride(ExtensionOverride node, {DartType? contextType}) {
+  void visitExtensionOverride(covariant ExtensionOverrideImpl node,
+      {DartType? contextType}) {
     var whyNotPromotedList = <Map<DartType, NonPromotionReason> Function()>[];
     node.extensionName.accept(this);
     node.typeArguments?.accept(this);
 
     var receiverContextType =
         ExtensionMemberResolver(this).computeOverrideReceiverContextType(node);
-    analyzeArgumentList(
-        node.argumentList,
-        receiverContextType == null
+    const ExtensionOverrideInferrer().resolveInvocation(
+        resolver: this,
+        node: node,
+        rawType: receiverContextType == null
             ? null
-            : [
-                ParameterElementImpl.synthetic(
-                    null, receiverContextType, ParameterKind.REQUIRED)
-              ],
+            : FunctionTypeImpl(
+                typeFormals: const [],
+                parameters: [
+                    ParameterElementImpl.synthetic(
+                        null, receiverContextType, ParameterKind.REQUIRED)
+                  ],
+                returnType: DynamicTypeImpl.instance,
+                nullabilitySuffix: NullabilitySuffix.none),
+        contextType: null,
         whyNotPromotedList: whyNotPromotedList);
 
     extensionResolver.resolveOverride(node, whyNotPromotedList);
@@ -2223,7 +2162,11 @@
     var whyNotPromotedList = <Map<DartType, NonPromotionReason> Function()>[];
     elementResolver.visitRedirectingConstructorInvocation(
         node as RedirectingConstructorInvocationImpl);
-    analyzeArgumentList(node.argumentList, node.staticElement?.parameters,
+    const RedirectingConstructorInvocationInferrer().resolveInvocation(
+        resolver: this,
+        node: node,
+        rawType: node.staticElement?.type,
+        contextType: null,
         whyNotPromotedList: whyNotPromotedList);
     checkForArgumentTypesNotAssignableInList(
         node.argumentList, whyNotPromotedList);
@@ -2327,7 +2270,11 @@
     var whyNotPromotedList = <Map<DartType, NonPromotionReason> Function()>[];
     elementResolver.visitSuperConstructorInvocation(
         node as SuperConstructorInvocationImpl);
-    analyzeArgumentList(node.argumentList, node.staticElement?.parameters,
+    const SuperConstructorInvocationInferrer().resolveInvocation(
+        resolver: this,
+        node: node,
+        rawType: node.staticElement?.type,
+        contextType: null,
         whyNotPromotedList: whyNotPromotedList);
     checkForArgumentTypesNotAssignableInList(
         node.argumentList, whyNotPromotedList);
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index a3ac1e3..946b08f 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -6,7 +6,6 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/extensions.dart';
-import 'package:analyzer/src/dart/element/member.dart' show ConstructorMember;
 import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
@@ -155,22 +154,6 @@
     node.staticType = _dynamicType;
   }
 
-  /// The Dart Language Specification, 12.11.1: <blockquote>The static type of a new expression of
-  /// either the form <i>new T.id(a<sub>1</sub>, &hellip;, a<sub>n</sub>)</i> or the form <i>new
-  /// T(a<sub>1</sub>, &hellip;, a<sub>n</sub>)</i> is <i>T</i>.</blockquote>
-  ///
-  /// The Dart Language Specification, 12.11.2: <blockquote>The static type of a constant object
-  /// expression of either the form <i>const T.id(a<sub>1</sub>, &hellip;, a<sub>n</sub>)</i> or the
-  /// form <i>const T(a<sub>1</sub>, &hellip;, a<sub>n</sub>)</i> is <i>T</i>. </blockquote>
-  void visitInstanceCreationExpression(
-      covariant InstanceCreationExpressionImpl node,
-      {required DartType? contextType}) {
-    _inferInstanceCreationExpression(node, contextType: contextType);
-    _inferenceHelper.recordStaticType(
-        node, node.constructorName.type.typeOrThrow,
-        contextType: contextType);
-  }
-
   /// <blockquote>
   /// An integer literal has static type \code{int}, unless the surrounding
   /// static context type is a type which \code{int} is not assignable to, and
@@ -342,56 +325,4 @@
     }
     return type;
   }
-
-  /// Given an instance creation of a possibly generic type, infer the type
-  /// arguments using the current context type as well as the argument types.
-  void _inferInstanceCreationExpression(InstanceCreationExpressionImpl node,
-      {required DartType? contextType}) {
-    // TODO(leafp): Currently, we may re-infer types here, since we
-    // sometimes resolve multiple times.  We should really check that we
-    // have not already inferred something.  However, the obvious ways to
-    // check this don't work, since we may have been instantiated
-    // to bounds in an earlier phase, and we *do* want to do inference
-    // in that case.
-
-    // Get back to the uninstantiated generic constructor.
-    // TODO(jmesserly): should we store this earlier in resolution?
-    // Or look it up, instead of jumping backwards through the Member?
-    var constructorName = node.constructorName;
-    var elementToInfer = _resolver.inferenceHelper.constructorElementToInfer(
-      constructorName: constructorName,
-      definingLibrary: _resolver.definingLibrary,
-    );
-
-    // If the constructor is not generic, we are done.
-    if (elementToInfer == null) {
-      return;
-    }
-
-    var typeName = constructorName.type;
-    var typeArguments = typeName.typeArguments;
-
-    var constructorType = elementToInfer.asType;
-    var arguments = node.argumentList;
-    var inferred = _resolver.inferenceHelper.inferGenericInvoke(
-        node, constructorType, typeArguments, arguments, constructorName,
-        isConst: node.isConst, contextReturnType: contextType);
-
-    if (inferred != null) {
-      // Fix up the parameter elements based on inferred method.
-      arguments.correspondingStaticParameters =
-          ResolverVisitor.resolveArgumentsToParameters(
-        argumentList: arguments,
-        parameters: inferred.parameters,
-      );
-      typeName.type = inferred.returnType;
-      // Update the static element as well. This is used in some cases, such as
-      // computing constant values. It is stored in two places.
-      var constructorElement = ConstructorMember.from(
-        elementToInfer.element,
-        inferred.returnType as InterfaceType,
-      );
-      constructorName.staticElement = constructorElement;
-    }
-  }
 }
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 456f594..bc4e648 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -1419,10 +1419,8 @@
 ''');
     var x = findNode.namedExpression('arg: true');
     var y = x.staticParameterElement!;
-    // Note: the staticParameterElement is synthetic; see
-    // https://github.com/dart-lang/sdk/issues/48500
-    expect(y, isNot(TypeMatcher<ParameterMember>()));
-    expect(y.enclosingElement, isNull);
+    expect(y, TypeMatcher<ParameterMember>());
+    expect(y.declaration, findElement.parameter('arg'));
   }
 
   test_generic_staticParameterElement_instanceCreation_implicitNew() async {
@@ -1447,10 +1445,8 @@
 ''');
     var x = findNode.namedExpression('arg: true');
     var y = x.staticParameterElement!;
-    // Note: the staticParameterElement is synthetic; see
-    // https://github.com/dart-lang/sdk/issues/48500
-    expect(y, isNot(TypeMatcher<ParameterMember>()));
-    expect(y.enclosingElement, isNull);
+    expect(y, TypeMatcher<ParameterMember>());
+    expect(y.declaration, findElement.parameter('arg'));
   }
 
   test_generic_staticParameterElement_methodCall() async {
diff --git a/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart b/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
index 2944a2b..a4c3dd6 100644
--- a/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
@@ -310,6 +310,21 @@
 ''');
   }
 
+  Future<void> test_nonFunctionTypeAlias_parameter() async {
+    await assertErrorsInCode('''
+class A {}
+class B extends A {}
+class D<T> {}
+typedef Alias<T extends B> = D<T>;
+main() {
+  D d = Alias<A>();
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 94, 1),
+      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 104, 1),
+    ]);
+  }
+
   test_notRegularBounded_notSuperBounded_parameter_invariant() async {
     await assertErrorsInCode(r'''
 typedef A<X> = X Function(X);
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
index 0783eff..133789f 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
@@ -366,11 +366,19 @@
     return js.Comment(generatedBy(_options, flavor: '$flavor'));
   }
 
-  js.Statement buildDeferredInitializerGlobal() {
-    return js.js.statement(
-        'self.#deferredInitializers = '
-        'self.#deferredInitializers || Object.create(null);',
-        {'deferredInitializers': deferredInitializersGlobal});
+  List<js.Statement> buildDeferredInitializerGlobal() {
+    return [
+      js.js.statement(
+          'self.#deferredInitializers = '
+          'self.#deferredInitializers || Object.create(null);',
+          {'deferredInitializers': deferredInitializersGlobal}),
+      if (_options.experimentalTrackAllocations)
+        js.js.statement(
+            'self.#deferredInitializers["allocations"] = '
+            'self.#deferredInitializers["allocations"] '
+            '|| Object.create(null)',
+            {'deferredInitializers': deferredInitializersGlobal})
+    ];
   }
 
   js.Statement buildStartupMetrics() {
@@ -421,7 +429,7 @@
     js.Program program = js.Program([
       buildGeneratedBy(),
       js.Comment(HOOKS_API_USAGE),
-      if (isSplit) buildDeferredInitializerGlobal(),
+      if (isSplit) ...buildDeferredInitializerGlobal(),
       if (_closedWorld.backendUsage.requiresStartupMetrics)
         buildStartupMetrics(),
       code
@@ -556,7 +564,7 @@
 
     js.Program program = js.Program([
       if (isFirst) buildGeneratedBy(),
-      if (isFirst) buildDeferredInitializerGlobal(),
+      if (isFirst) ...buildDeferredInitializerGlobal(),
       if (_options.experimentalTrackAllocations)
         js.js.statement("var allocations = #deferredGlobal['allocations']",
             {'deferredGlobal': deferredInitializersGlobal}),
diff --git a/tools/VERSION b/tools/VERSION
index b27473d..96ecaf9 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 17
 PATCH 0
-PRERELEASE 180
+PRERELEASE 181
 PRERELEASE_PATCH 0
\ No newline at end of file