| Index: pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
|
| diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
|
| index cb360020e16c3bbfbf61a497c3cd1edb2253d5ec..5af584a6e371183142e3347f19991fa7d8647b01 100644
|
| --- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
|
| +++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
|
| @@ -593,8 +593,19 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> {
|
| var receiverType = inferExpression(receiver, null, true);
|
| // TODO(paulberry): can we share some of the code below with
|
| // inferConstructorInvocation?
|
| + bool isOverloadedArithmeticOperator = false;
|
| + Member interfaceMember;
|
| + if (receiverType is InterfaceType) {
|
| + interfaceMember =
|
| + classHierarchy.getInterfaceMember(receiverType.classNode, methodName);
|
| + if (interfaceMember is Procedure) {
|
| + setInterfaceTarget(interfaceMember);
|
| + isOverloadedArithmeticOperator = typeSchemaEnvironment
|
| + .isOverloadedArithmeticOperator(interfaceMember);
|
| + }
|
| + }
|
| var memberFunctionType = _getCalleeFunctionType(
|
| - receiverType, methodName, offset, setInterfaceTarget);
|
| + interfaceMember, receiverType, methodName, offset);
|
| List<TypeParameter> memberTypeParameters =
|
| memberFunctionType.typeParameters;
|
| bool inferenceNeeded = explicitTypeArguments == null &&
|
| @@ -623,6 +634,7 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> {
|
| substitution =
|
| Substitution.fromPairs(memberTypeParameters, explicitTypeArguments);
|
| }
|
| + DartType returnType = memberFunctionType.returnType;
|
| int i = 0;
|
| forEachArgument((name, expression) {
|
| DartType formalType = name != null
|
| @@ -631,16 +643,20 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> {
|
| DartType inferredFormalType = substitution != null
|
| ? substitution.substituteType(formalType)
|
| : formalType;
|
| - var expressionType =
|
| - inferExpression(expression, inferredFormalType, inferenceNeeded);
|
| + var expressionType = inferExpression(expression, inferredFormalType,
|
| + inferenceNeeded || isOverloadedArithmeticOperator);
|
| if (inferenceNeeded) {
|
| formalTypes.add(formalType);
|
| actualTypes.add(expressionType);
|
| }
|
| + if (isOverloadedArithmeticOperator) {
|
| + returnType = typeSchemaEnvironment.getTypeOfOverloadedArithmetic(
|
| + receiverType, expressionType);
|
| + }
|
| });
|
| if (inferenceNeeded) {
|
| typeSchemaEnvironment.inferGenericFunctionOrType(
|
| - memberFunctionType.returnType,
|
| + returnType,
|
| memberTypeParameters,
|
| formalTypes,
|
| actualTypes,
|
| @@ -655,8 +671,8 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> {
|
| DartType inferredType;
|
| if (typeNeeded) {
|
| inferredType = substitution == null
|
| - ? memberFunctionType.returnType
|
| - : substitution.substituteType(memberFunctionType.returnType);
|
| + ? returnType
|
| + : substitution.substituteType(returnType);
|
| }
|
| listener.methodInvocationExit(inferredType);
|
| return inferredType;
|
| @@ -779,18 +795,15 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> {
|
| return inferredType;
|
| }
|
|
|
| - FunctionType _getCalleeFunctionType(DartType receiverType, Name methodName,
|
| - int offset, void setInterfaceTarget(Procedure procedure)) {
|
| + FunctionType _getCalleeFunctionType(Member interfaceMember,
|
| + DartType receiverType, Name methodName, int offset) {
|
| if (receiverType is InterfaceType) {
|
| - var member =
|
| - classHierarchy.getInterfaceMember(receiverType.classNode, methodName);
|
| - if (member == null) return _functionReturningDynamic;
|
| - var memberClass = member.enclosingClass;
|
| - if (member is Procedure) {
|
| + if (interfaceMember == null) return _functionReturningDynamic;
|
| + var memberClass = interfaceMember.enclosingClass;
|
| + if (interfaceMember is Procedure) {
|
| instrumentation?.record(Uri.parse(uri), offset, 'target',
|
| - new InstrumentationValueForProcedure(member));
|
| - setInterfaceTarget(member);
|
| - var memberFunctionType = member.function.functionType;
|
| + new InstrumentationValueForProcedure(interfaceMember));
|
| + var memberFunctionType = interfaceMember.function.functionType;
|
| if (memberClass.typeParameters.isNotEmpty) {
|
| var castedType = classHierarchy.getClassAsInstanceOf(
|
| receiverType.classNode, memberClass);
|
| @@ -801,7 +814,7 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> {
|
| .substituteType(memberFunctionType);
|
| }
|
| return memberFunctionType;
|
| - } else if (member is Field) {
|
| + } else if (interfaceMember is Field) {
|
| // TODO(paulberry): handle this case
|
| return _functionReturningDynamic;
|
| } else {
|
|
|