| 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 106ff7a72ab22d64c6f9e751b95558ad7414b8e3..b4ca685b99477835166c32bd459aa2d276ce10b7 100644
|
| --- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
|
| +++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
|
| @@ -726,7 +726,7 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| _resolver.recordPropagatedTypeIfBetter(methodNameNode, propagatedType);
|
| }
|
| // Record static return type of the static element.
|
| - DartType staticStaticType = _computeStaticReturnType(staticMethodElement);
|
| + DartType staticStaticType = _computeInvokeReturnType(node.staticInvokeType);
|
| _recordStaticType(node, staticStaticType);
|
| // Record propagated return type of the static element.
|
| DartType staticPropagatedType =
|
| @@ -736,12 +736,6 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| bool needPropagatedType = true;
|
| String methodName = methodNameNode.name;
|
| if (_strongMode) {
|
| - // TODO(leafp): Revisit this. It's here to associate a type with the
|
| - // method name, which is important to the DDC backend (but apparently
|
| - // no-one else). Not sure that there's a problem having this here, but
|
| - // it's a little ad hoc.
|
| - visitSimpleIdentifier(methodNameNode);
|
| -
|
| _inferMethodInvocation(node);
|
| }
|
| if (methodName == "then") {
|
| @@ -1438,38 +1432,28 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| //
|
| FunctionType propertyType = element.type;
|
| if (propertyType != null) {
|
| - DartType returnType = propertyType.returnType;
|
| - if (returnType.isDartCoreFunction) {
|
| - return _dynamicType;
|
| - } else if (returnType is InterfaceType) {
|
| - MethodElement callMethod = returnType.lookUpMethod(
|
| - FunctionElement.CALL_METHOD_NAME, _resolver.definingLibrary);
|
| - if (callMethod != null) {
|
| - return callMethod.type.returnType;
|
| - }
|
| - } else if (returnType is FunctionType) {
|
| - DartType innerReturnType = returnType.returnType;
|
| - if (innerReturnType != null) {
|
| - return innerReturnType;
|
| - }
|
| - }
|
| - if (returnType != null) {
|
| - return returnType;
|
| - }
|
| + return _computeInvokeReturnType(propertyType.returnType);
|
| }
|
| } else if (element is ExecutableElement) {
|
| - FunctionType type = element.type;
|
| - if (type != null) {
|
| - // TODO(brianwilkerson) Figure out the conditions under which the type
|
| - // is null.
|
| - return type.returnType;
|
| - }
|
| + return _computeInvokeReturnType(element.type);
|
| } else if (element is VariableElement) {
|
| - VariableElement variable = element;
|
| - DartType variableType = _promoteManager.getStaticType(variable);
|
| - if (variableType is FunctionType) {
|
| - return variableType.returnType;
|
| - }
|
| + DartType variableType = _promoteManager.getStaticType(element);
|
| + return _computeInvokeReturnType(variableType);
|
| + }
|
| + return _dynamicType;
|
| + }
|
| +
|
| + /**
|
| + * 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;
|
| }
|
| @@ -1823,58 +1807,41 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| */
|
| bool _inferMethodInvocationGeneric(MethodInvocation node) {
|
| Element element = node.methodName.staticElement;
|
| - DartType fnType = node.methodName.staticType;
|
| + DartType invokeType = node.staticInvokeType;
|
| +
|
| TypeSystem ts = _typeSystem;
|
| if (node.typeArguments == null &&
|
| element is ExecutableElement &&
|
| - fnType is FunctionTypeImpl &&
|
| ts is StrongTypeSystemImpl) {
|
| - FunctionTypeImpl genericFunction = fnType.originalFunction;
|
| - if (element is PropertyAccessorElement) {
|
| - genericFunction = element.type.returnType;
|
| - }
|
| - if (genericFunction.boundTypeParameters.isEmpty) {
|
| - return false;
|
| - }
|
| - for (DartType typeArg in fnType.instantiatedTypeArguments) {
|
| - if (!typeArg.isDynamic) {
|
| - return false;
|
| + FunctionType fnType = element.type;
|
| + if (fnType.typeFormals.isNotEmpty &&
|
| + ts.instantiateToBounds(fnType) == invokeType) {
|
| + // Get the parameters that correspond to the uninstantiated generic.
|
| + List<ParameterElement> genericParameters =
|
| + ResolverVisitor.resolveArgumentsToParameters(
|
| + node.argumentList, fnType.parameters, null);
|
| +
|
| + int length = genericParameters.length;
|
| + List<DartType> argTypes = new List<DartType>(length);
|
| + List<DartType> paramTypes = new List<DartType>(length);
|
| + for (int i = 0; i < length; i++) {
|
| + argTypes[i] = node.argumentList.arguments[i].staticType;
|
| + paramTypes[i] = genericParameters[i].type;
|
| }
|
| - }
|
| -
|
| - List<ParameterElement> genericParameters = genericFunction.parameters;
|
| - List<DartType> argTypes = new List<DartType>();
|
| - List<DartType> paramTypes = new List<DartType>();
|
| - for (Expression arg in node.argumentList.arguments) {
|
| - // We may have too many (or too few) arguments. Only use arguments
|
| - // which have been matched up with a static parameter.
|
| - ParameterElement p = arg.staticParameterElement;
|
| - if (p != null) {
|
| - int i = element.parameters.indexOf(p);
|
| - argTypes.add(arg.staticType);
|
| - paramTypes.add(genericParameters[i].type);
|
| - }
|
| - }
|
|
|
| - FunctionType inferred = ts.inferCallFromArguments(
|
| - _typeProvider, genericFunction, paramTypes, argTypes);
|
| - if (inferred != fnType) {
|
| - // TODO(jmesserly): we need to fix up the parameter elements based on
|
| - // inferred method.
|
| - List<ParameterElement> inferredParameters = inferred.parameters;
|
| - List<ParameterElement> correspondingParams =
|
| - new List<ParameterElement>();
|
| - for (Expression arg in node.argumentList.arguments) {
|
| - ParameterElement p = arg.staticParameterElement;
|
| - if (p != null) {
|
| - int i = element.parameters.indexOf(p);
|
| - correspondingParams.add(inferredParameters[i]);
|
| - }
|
| + 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;
|
| }
|
| - node.argumentList.correspondingStaticParameters = correspondingParams;
|
| - _recordStaticType(node.methodName, inferred);
|
| - _recordStaticType(node, inferred.returnType);
|
| - return true;
|
| }
|
| }
|
| return false;
|
| @@ -1934,7 +1901,7 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| inferredType.parameters.isEmpty &&
|
| node.argumentList.arguments.isEmpty &&
|
| _typeProvider.nonSubtypableTypes.contains(inferredType.returnType)) {
|
| - _recordStaticType(node.methodName, inferredType);
|
| + node.staticInvokeType = inferredType;
|
| _recordStaticType(node, inferredType.returnType);
|
| return true;
|
| }
|
|
|