| Index: lib/src/checker/rules.dart
|
| diff --git a/lib/src/checker/rules.dart b/lib/src/checker/rules.dart
|
| index 4d0317c2cbd0533f8c8e0e62f4671ccdd3758c6d..8ea21879318fbaef5bfff6b98984ef1fa72c5342 100644
|
| --- a/lib/src/checker/rules.dart
|
| +++ b/lib/src/checker/rules.dart
|
| @@ -42,6 +42,32 @@ abstract class TypeRules {
|
|
|
| DartType getStaticType(Expression expr) => expr.staticType;
|
|
|
| + /// Given a type t, if t is an interface type with a call method
|
| + /// defined, return the function type for the call method, otherwise
|
| + /// return null.
|
| + FunctionType getCallMethodType(DartType t) {
|
| + if (t is InterfaceType) {
|
| + ClassElement element = t.element;
|
| + InheritanceManager manager = new InheritanceManager(element.library);
|
| + FunctionType callType = manager.lookupMemberType(t, "call");
|
| + return callType;
|
| + }
|
| + return null;
|
| + }
|
| +
|
| + /// Given an expression, return its type assuming it is
|
| + /// in the caller position of a call (that is, accounting
|
| + /// for the possibility of a call method). Returns null
|
| + /// if expression is not statically callable.
|
| + FunctionType getTypeAsCaller(Expression applicand) {
|
| + var t = getStaticType(applicand);
|
| + if (t is InterfaceType) {
|
| + return getCallMethodType(t);
|
| + }
|
| + if (t is FunctionType) return t;
|
| + return null;
|
| + }
|
| +
|
| DartType elementType(Element e);
|
|
|
| bool isDynamic(DartType t);
|
| @@ -185,16 +211,6 @@ class RestrictedRules extends TypeRules {
|
| throw new StateError("Unexpected type");
|
| }
|
|
|
| - FunctionType getCallMethodType(DartType t) {
|
| - if (t is InterfaceType) {
|
| - ClassElement element = t.element;
|
| - InheritanceManager manager = new InheritanceManager(element.library);
|
| - FunctionType callType = manager.lookupMemberType(t, "call");
|
| - return callType;
|
| - }
|
| - return null;
|
| - }
|
| -
|
| /// Check that f1 is a subtype of f2. [ignoreReturn] is used in the DDC
|
| /// checker to determine whether f1 would be a subtype of f2 if the return
|
| /// type of f1 is set to match f2's return type.
|
| @@ -536,12 +552,12 @@ class RestrictedRules extends TypeRules {
|
| /// invocation.
|
| bool isDynamicCall(Expression call) {
|
| if (options.ignoreTypes) return true;
|
| - var t = getStaticType(call);
|
| - // TODO(jmesserly): fix handling of types with `call` methods. These are not
|
| - // FunctionType, but they also aren't dynamic calls.
|
| - if (t.isDynamic || t.isDartCoreFunction || t is! FunctionType) {
|
| - return true;
|
| - }
|
| + var t = getTypeAsCaller(call);
|
| + // TODO(leafp): This will currently return true if t is Function
|
| + // This is probably the most correct thing to do for now, since
|
| + // this code is also used by the back end. Maybe revisit at some
|
| + // point?
|
| + if (t == null) return true;
|
| // Dynamic as the parameter type is treated as bottom. A function with
|
| // a dynamic parameter type requires a dynamic call in general.
|
| // However, as an optimization, if we have an original definition, we know
|
|
|