Index: pkg/kernel/lib/type_checker.dart |
diff --git a/pkg/kernel/lib/type_checker.dart b/pkg/kernel/lib/type_checker.dart |
index f32ae870cdd3f9a133f171d228c6e5397633e9c4..2d7fb5804b0097036633b346607ca92e661b44ad 100644 |
--- a/pkg/kernel/lib/type_checker.dart |
+++ b/pkg/kernel/lib/type_checker.dart |
@@ -248,56 +248,64 @@ class TypeCheckingVisitor |
hierarchy.getClassAsInstanceOf(currentClass, member.enclosingClass)); |
} |
- DartType handleCall(Arguments arguments, FunctionNode function, |
+ DartType handleCall(Arguments arguments, DartType functionType, |
{Substitution receiver: Substitution.empty, |
List<TypeParameter> typeParameters}) { |
- typeParameters ??= function.typeParameters; |
- if (arguments.positional.length < function.requiredParameterCount) { |
- fail(arguments, 'Too few positional arguments'); |
- return const BottomType(); |
- } |
- if (arguments.positional.length > function.positionalParameters.length) { |
- fail(arguments, 'Too many positional arguments'); |
- return const BottomType(); |
- } |
- if (arguments.types.length != typeParameters.length) { |
- fail(arguments, 'Wrong number of type arguments'); |
- return const BottomType(); |
- } |
- var instantiation = Substitution.fromPairs(typeParameters, arguments.types); |
- var substitution = Substitution.combine(receiver, instantiation); |
- for (int i = 0; i < typeParameters.length; ++i) { |
- var argument = arguments.types[i]; |
- var bound = substitution.substituteType(typeParameters[i].bound); |
- checkAssignable(arguments, argument, bound); |
- } |
- for (int i = 0; i < arguments.positional.length; ++i) { |
- var expectedType = substitution.substituteType( |
- function.positionalParameters[i].type, |
- contravariant: true); |
- arguments.positional[i] = |
- checkAndDowncastExpression(arguments.positional[i], expectedType); |
- } |
- for (int i = 0; i < arguments.named.length; ++i) { |
- var argument = arguments.named[i]; |
- bool found = false; |
- for (int j = 0; j < function.namedParameters.length; ++j) { |
- if (argument.name == function.namedParameters[j].name) { |
- var expectedType = substitution.substituteType( |
- function.namedParameters[j].type, |
- contravariant: true); |
- argument.value = |
- checkAndDowncastExpression(argument.value, expectedType); |
- found = true; |
- break; |
- } |
+ if (functionType is FunctionType) { |
+ typeParameters ??= functionType.typeParameters; |
+ if (arguments.positional.length < functionType.requiredParameterCount) { |
+ fail(arguments, 'Too few positional arguments'); |
+ return const BottomType(); |
} |
- if (!found) { |
- fail(argument.value, 'Unexpected named parameter: ${argument.name}'); |
+ if (arguments.positional.length > |
+ functionType.positionalParameters.length) { |
+ fail(arguments, 'Too many positional arguments'); |
return const BottomType(); |
} |
+ if (arguments.types.length != typeParameters.length) { |
+ fail(arguments, 'Wrong number of type arguments'); |
+ return const BottomType(); |
+ } |
+ var instantiation = |
+ Substitution.fromPairs(typeParameters, arguments.types); |
+ var substitution = Substitution.combine(receiver, instantiation); |
+ for (int i = 0; i < typeParameters.length; ++i) { |
+ var argument = arguments.types[i]; |
+ var bound = substitution.substituteType(typeParameters[i].bound); |
+ checkAssignable(arguments, argument, bound); |
+ } |
+ for (int i = 0; i < arguments.positional.length; ++i) { |
+ var expectedType = substitution.substituteType( |
+ functionType.positionalParameters[i], |
+ contravariant: true); |
+ arguments.positional[i] = |
+ checkAndDowncastExpression(arguments.positional[i], expectedType); |
+ } |
+ for (int i = 0; i < arguments.named.length; ++i) { |
+ var argument = arguments.named[i]; |
+ bool found = false; |
+ for (int j = 0; j < functionType.namedParameters.length; ++j) { |
+ if (argument.name == functionType.namedParameters[j].name) { |
+ var expectedType = substitution.substituteType( |
+ functionType.namedParameters[j].type, |
+ contravariant: true); |
+ argument.value = |
+ checkAndDowncastExpression(argument.value, expectedType); |
+ found = true; |
+ break; |
+ } |
+ } |
+ if (!found) { |
+ fail(argument.value, 'Unexpected named parameter: ${argument.name}'); |
+ return const BottomType(); |
+ } |
+ } |
+ return substitution.substituteType(functionType.returnType); |
+ } else { |
+ // Note: attempting to resolve .call() on [functionType] could lead to an |
+ // infinite regress, so just assume `dynamic`. |
+ return const DynamicType(); |
} |
- return substitution.substituteType(function.returnType); |
} |
DartType _getInternalReturnType(FunctionNode function) { |
@@ -379,14 +387,14 @@ class TypeCheckingVisitor |
Constructor target = node.target; |
Arguments arguments = node.arguments; |
Class class_ = target.enclosingClass; |
- handleCall(arguments, target.function, |
+ handleCall(arguments, target.function.functionType, |
typeParameters: class_.typeParameters); |
return new InterfaceType(target.enclosingClass, arguments.types); |
} |
@override |
DartType visitDirectMethodInvocation(DirectMethodInvocation node) { |
- return handleCall(node.arguments, node.target.function, |
+ return handleCall(node.arguments, node.target.getterType, |
receiver: getReceiverType(node, node.receiver, node.target)); |
} |
@@ -524,13 +532,14 @@ class TypeCheckingVisitor |
return handleFunctionCall(node, receiver, node.arguments); |
} |
return handleDynamicCall(receiver, node.arguments); |
- } else if (environment.isOverloadedArithmeticOperator(target)) { |
+ } else if (target is Procedure && |
+ environment.isOverloadedArithmeticOperator(target)) { |
assert(node.arguments.positional.length == 1); |
var receiver = visitExpression(node.receiver); |
var argument = visitExpression(node.arguments.positional[0]); |
return environment.getTypeOfOverloadedArithmetic(receiver, argument); |
} else { |
- return handleCall(node.arguments, target.function, |
+ return handleCall(node.arguments, target.getterType, |
receiver: getReceiverType(node, node.receiver, node.interfaceTarget)); |
} |
} |
@@ -585,7 +594,7 @@ class TypeCheckingVisitor |
@override |
DartType visitStaticInvocation(StaticInvocation node) { |
- return handleCall(node.arguments, node.target.function); |
+ return handleCall(node.arguments, node.target.getterType); |
} |
@override |
@@ -611,7 +620,7 @@ class TypeCheckingVisitor |
if (node.interfaceTarget == null) { |
return handleDynamicCall(environment.thisType, node.arguments); |
} else { |
- return handleCall(node.arguments, node.interfaceTarget.function, |
+ return handleCall(node.arguments, node.interfaceTarget.getterType, |
receiver: getSuperReceiverType(node.interfaceTarget)); |
} |
} |
@@ -937,13 +946,13 @@ class TypeCheckingVisitor |
@override |
visitRedirectingInitializer(RedirectingInitializer node) { |
- handleCall(node.arguments, node.target.function, |
+ handleCall(node.arguments, node.target.getterType, |
typeParameters: const <TypeParameter>[]); |
} |
@override |
visitSuperInitializer(SuperInitializer node) { |
- handleCall(node.arguments, node.target.function, |
+ handleCall(node.arguments, node.target.getterType, |
typeParameters: const <TypeParameter>[], |
receiver: getSuperReceiverType(node.target)); |
} |