| 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 a2eba70eece785e7554bd6638ac0da2bd6ff78e2..2539c8d934033bbc8e7ca2e54f8dd6bd2851458e 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
|
| @@ -26,6 +26,7 @@ import 'package:kernel/ast.dart'
|
| Member,
|
| Name,
|
| Procedure,
|
| + ProcedureKind,
|
| Statement,
|
| TypeParameterType,
|
| VariableDeclaration,
|
| @@ -206,44 +207,58 @@ abstract class TypeInferrerImpl extends TypeInferrer {
|
|
|
| FunctionType getCalleeFunctionType(
|
| Member interfaceMember, DartType receiverType, Name methodName) {
|
| + var type = getCalleeType(interfaceMember, receiverType, methodName);
|
| + if (type is FunctionType) {
|
| + return type;
|
| + } else {
|
| + return _functionReturningDynamic;
|
| + }
|
| + }
|
| +
|
| + DartType getCalleeType(
|
| + Member interfaceMember, DartType receiverType, Name methodName) {
|
| if (receiverType is InterfaceType) {
|
| - if (interfaceMember == null) return _functionReturningDynamic;
|
| + if (interfaceMember == null) return const DynamicType();
|
| var memberClass = interfaceMember.enclosingClass;
|
| + DartType calleeType;
|
| if (interfaceMember is Procedure) {
|
| - var memberFunctionType = interfaceMember.function.functionType;
|
| - if (memberClass.typeParameters.isNotEmpty) {
|
| - var castedType = classHierarchy.getClassAsInstanceOf(
|
| - receiverType.classNode, memberClass);
|
| - memberFunctionType = Substitution
|
| - .fromInterfaceType(Substitution
|
| - .fromInterfaceType(receiverType)
|
| - .substituteType(castedType.asInterfaceType))
|
| - .substituteType(memberFunctionType);
|
| + if (interfaceMember.kind == ProcedureKind.Getter) {
|
| + calleeType = interfaceMember.function.returnType;
|
| + } else {
|
| + calleeType = interfaceMember.function.functionType;
|
| }
|
| - return memberFunctionType;
|
| } else if (interfaceMember is Field) {
|
| - // TODO(paulberry): handle this case
|
| - return _functionReturningDynamic;
|
| + calleeType = interfaceMember.type;
|
| } else {
|
| - return _functionReturningDynamic;
|
| + calleeType = const DynamicType();
|
| }
|
| + if (memberClass.typeParameters.isNotEmpty) {
|
| + var castedType = classHierarchy.getClassAsInstanceOf(
|
| + receiverType.classNode, memberClass);
|
| + calleeType = Substitution
|
| + .fromInterfaceType(Substitution
|
| + .fromInterfaceType(receiverType)
|
| + .substituteType(castedType.asInterfaceType))
|
| + .substituteType(calleeType);
|
| + }
|
| + return calleeType;
|
| } else if (receiverType is DynamicType) {
|
| - return _functionReturningDynamic;
|
| + return const DynamicType();
|
| } else if (receiverType is FunctionType) {
|
| if (methodName.name == 'call') {
|
| return receiverType;
|
| } else {
|
| // TODO(paulberry): handle the case of invoking .toString() on a
|
| // function type.
|
| - return _functionReturningDynamic;
|
| + return const DynamicType();
|
| }
|
| } else if (receiverType is TypeParameterType) {
|
| // TODO(paulberry): use the bound
|
| - return _functionReturningDynamic;
|
| + return const DynamicType();
|
| } else {
|
| // TODO(paulberry): handle the case of invoking .toString() on a type
|
| // that's none of the above (e.g. `dynamic` or `bottom`)
|
| - return _functionReturningDynamic;
|
| + return const DynamicType();
|
| }
|
| }
|
|
|
|
|