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>, …, a<sub>n</sub>)</i> or the form <i>new
- /// T(a<sub>1</sub>, …, 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>, …, a<sub>n</sub>)</i> or the
- /// form <i>const T(a<sub>1</sub>, …, 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