Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(638)

Unified Diff: pkg/analyzer/lib/src/generated/static_type_analyzer.dart

Issue 1586813002: fix #25425, more inference of generic methods (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: rebase Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/analyzer/lib/src/generated/static_type_analyzer.dart
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index a034cbb3007b3cf5c624ff85b2c89e6b1c1062f3..712cb5589d91cf838858d96b5ab7dfb2e92cff8c 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -495,6 +495,9 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
*/
@override
Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+ if (_strongMode) {
+ _inferFunctionInvocationGeneric(node);
+ }
DartType staticType = _computeInvokeReturnType(node.staticInvokeType);
_recordStaticType(node, staticType);
DartType functionPropagatedType = node.propagatedInvokeType;
@@ -713,12 +716,12 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
Object visitMethodInvocation(MethodInvocation node) {
SimpleIdentifier methodNameNode = node.methodName;
Element staticMethodElement = methodNameNode.staticElement;
+ if (_strongMode) {
+ _inferMethodInvocation(node);
+ }
// Record types of the variable invoked as a function.
if (staticMethodElement is VariableElement) {
- VariableElement variable = staticMethodElement;
- DartType staticType = variable.type;
- _recordStaticType(methodNameNode, staticType);
- DartType propagatedType = _overrideManager.getType(variable);
+ DartType propagatedType = _overrideManager.getType(staticMethodElement);
_resolver.recordPropagatedTypeIfBetter(methodNameNode, propagatedType);
}
// Record static return type of the static element.
@@ -731,9 +734,6 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
// Check for special cases.
bool needPropagatedType = true;
String methodName = methodNameNode.name;
- if (_strongMode) {
- _inferMethodInvocation(node);
- }
if (methodName == "then") {
Expression target = node.realTarget;
if (target != null) {
@@ -1384,6 +1384,21 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
}
/**
+ * 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 InterfaceType) {
+ MethodElement callMethod = type.lookUpMethod(
+ FunctionElement.CALL_METHOD_NAME, _resolver.definingLibrary);
+ return callMethod?.type?.returnType ?? _dynamicType;
+ } else if (type is FunctionType) {
+ return type.returnType ?? _dynamicType;
+ }
+ return _dynamicType;
+ }
+
+ /**
* Compute the propagated return type of the method or function represented by the given element.
*
* @param element the element representing the method or function invoked by the given node
@@ -1445,21 +1460,6 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
}
/**
- * 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 InterfaceType) {
- MethodElement callMethod = type.lookUpMethod(
- FunctionElement.CALL_METHOD_NAME, _resolver.definingLibrary);
- return callMethod?.type?.returnType ?? _dynamicType;
- } else if (type is FunctionType) {
- return type.returnType ?? _dynamicType;
- }
- return _dynamicType;
- }
-
- /**
* Given a function declaration, compute the return static type of the function. The return type
* of functions with a block body is `dynamicType`, with an expression body it is the type
* of the expression.
@@ -1774,6 +1774,63 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
}
/**
+ * Similar to [_inferMethodInvocationGeneric] but for function expression
+ * invocations.
+ */
+ // TODO(jmesserly): if we had a common AST interface between these two nodes,
+ // we could remove this duplicated code.
+ bool _inferFunctionInvocationGeneric(FunctionExpressionInvocation node) {
+ DartType instantiatedType = node.staticInvokeType;
+ DartType originalType = node.function.staticType;
+ if (instantiatedType is FunctionType && originalType is FunctionType) {
+ FunctionType inferred = _inferGenericInvoke(instantiatedType,
+ originalType, node.typeArguments, node.argumentList);
+ if (inferred != null) {
+ node.staticInvokeType = inferred;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ FunctionType _inferGenericInvoke(FunctionType invokeType, FunctionType fnType,
+ TypeArgumentList typeArguments, ArgumentList argumentList) {
+ TypeSystem ts = _typeSystem;
+ if (typeArguments == null && ts is StrongTypeSystemImpl) {
+ if (fnType.typeFormals.isNotEmpty &&
+ ts.instantiateToBounds(fnType) == invokeType) {
+ // Get the parameters that correspond to the uninstantiated generic.
+ List<ParameterElement> rawParameters =
+ ResolverVisitor.resolveArgumentsToParameters(
+ argumentList, fnType.parameters, null);
+
+ List<DartType> paramTypes = <DartType>[];
+ List<DartType> argTypes = <DartType>[];
+ for (int i = 0, length = rawParameters.length; i < length; i++) {
+ ParameterElement parameter = rawParameters[i];
+ if (parameter != null) {
+ paramTypes.add(parameter.type);
+ argTypes.add(argumentList.arguments[i].staticType);
+ }
+ }
+
+ FunctionType inferred = ts.inferCallFromArguments(
+ _typeProvider, fnType, paramTypes, argTypes);
+
+ if (inferred != fnType) {
+ // Fix up the parameter elements based on inferred method.
+ List<ParameterElement> inferredParameters =
+ ResolverVisitor.resolveArgumentsToParameters(
+ argumentList, inferred.parameters, null);
+ argumentList.correspondingStaticParameters = inferredParameters;
+ return inferred;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
* Given a local variable declaration and its initializer, attempt to infer
* a type for the local variable declaration based on the initializer.
* Inference is only done if an explicit type is not present, and if
@@ -1807,44 +1864,17 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
* type variables, using the actual types of the arguments.
*/
bool _inferMethodInvocationGeneric(MethodInvocation node) {
- Element element = node.methodName.staticElement;
- DartType invokeType = node.staticInvokeType;
-
- TypeSystem ts = _typeSystem;
- if (node.typeArguments == null &&
- element is ExecutableElement &&
- ts is StrongTypeSystemImpl) {
- FunctionType fnType = element.type;
- if (fnType.typeFormals.isNotEmpty &&
- ts.instantiateToBounds(fnType) == invokeType) {
- // Get the parameters that correspond to the uninstantiated generic.
- List<ParameterElement> rawParameters =
- ResolverVisitor.resolveArgumentsToParameters(
- node.argumentList, fnType.parameters, null);
-
- List<DartType> paramTypes = <DartType>[];
- List<DartType> argTypes = <DartType>[];
- for (int i = 0, length = rawParameters.length; i < length; i++) {
- ParameterElement parameter = rawParameters[i];
- if (parameter != null) {
- paramTypes.add(parameter.type);
- argTypes.add(node.argumentList.arguments[i].staticType);
- }
- }
-
- FunctionType inferred = ts.inferCallFromArguments(
- _typeProvider, fnType, paramTypes, argTypes);
-
- if (inferred != fnType) {
- // Fix up the parameter elements based on inferred method.
- List<ParameterElement> inferredParameters =
- ResolverVisitor.resolveArgumentsToParameters(
- node.argumentList, inferred.parameters, null);
- node.argumentList.correspondingStaticParameters = inferredParameters;
- node.staticInvokeType = inferred;
- _recordStaticType(node, inferred.returnType);
- return true;
- }
+ DartType instantiatedType = node.staticInvokeType;
+ DartType originalType = node.methodName.staticType;
+ // TODO(jmesserly): support generic `call` methods.
+ // Perhaps we should always record a FunctionType in staticInvokeType
+ // and the methodName's staticType.
+ if (instantiatedType is FunctionType && originalType is FunctionType) {
+ FunctionType inferred = _inferGenericInvoke(instantiatedType,
+ originalType, node.typeArguments, node.argumentList);
+ if (inferred != null) {
+ node.staticInvokeType = inferred;
+ return true;
}
}
return false;
@@ -1897,7 +1927,7 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
return false;
}
DartType inferredType = inferredElement.type;
- DartType nodeType = node.staticType;
+ DartType nodeType = node.staticInvokeType;
if (nodeType != null &&
nodeType.isDynamic &&
inferredType is FunctionType &&
« no previous file with comments | « pkg/analyzer/lib/src/generated/element_resolver.dart ('k') | pkg/analyzer/test/generated/resolver_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698