Fix more-specific for interface types with call functions.

R=ahe@google.com

Review URL: https://codereview.chromium.org/2307873002 .
diff --git a/pkg/compiler/lib/src/dart_types.dart b/pkg/compiler/lib/src/dart_types.dart
index 271d09f..4482d34 100644
--- a/pkg/compiler/lib/src/dart_types.dart
+++ b/pkg/compiler/lib/src/dart_types.dart
@@ -1027,6 +1027,8 @@
 
   bool invalidTypeVariableBounds(DartType bound, DartType s);
 
+  bool invalidCallableType(DartType callType, DartType s);
+
   /// Handle as dynamic for both subtype and more specific relation to avoid
   /// spurious errors from malformed types.
   bool visitMalformedType(MalformedType t, DartType s) => true;
@@ -1050,10 +1052,19 @@
 
     if (s is InterfaceType) {
       InterfaceType instance = t.asInstanceOf(s.element);
-      return instance != null && checkTypeArguments(instance, s);
-    } else {
-      return false;
+      if (instance != null && checkTypeArguments(instance, s)) {
+        return true;
+      }
     }
+
+    if (s == coreTypes.functionType && t.element.callType != null) {
+      return true;
+    } else if (s is FunctionType) {
+      FunctionType callType = t.callType;
+      return callType != null && !invalidCallableType(callType, s);
+    }
+
+    return false;
   }
 
   bool visitFunctionType(FunctionType t, DartType s) {
@@ -1223,6 +1234,10 @@
   bool invalidTypeVariableBounds(DartType bound, DartType s) {
     return !isMoreSpecific(bound, s);
   }
+
+  bool invalidCallableType(DartType callType, DartType s) {
+    return !isMoreSpecific(callType, s);
+  }
 }
 
 /**
@@ -1255,16 +1270,8 @@
     return !isSubtype(bound, s);
   }
 
-  bool visitInterfaceType(InterfaceType t, DartType s) {
-    if (super.visitInterfaceType(t, s)) return true;
-
-    if (s == coreTypes.functionType && t.element.callType != null) {
-      return true;
-    } else if (s is FunctionType) {
-      FunctionType callType = t.callType;
-      return callType != null && isSubtype(callType, s);
-    }
-    return false;
+  bool invalidCallableType(DartType callType, DartType s) {
+    return !isSubtype(callType, s);
   }
 }
 
diff --git a/tests/compiler/dart2js/subtype_test.dart b/tests/compiler/dart2js/subtype_test.dart
index bdd9e66..b31e2d8 100644
--- a/tests/compiler/dart2js/subtype_test.dart
+++ b/tests/compiler/dart2js/subtype_test.dart
@@ -277,18 +277,21 @@
     ClassElement classA = env.getElement('A');
     DartType A = classA.rawType;
     DartType function = env['Function'];
+    DartType call = env.getMemberType(classA, 'call');
     DartType m1 = env.getMemberType(classA, 'm1');
     DartType m2 = env.getMemberType(classA, 'm2');
     DartType m3 = env.getMemberType(classA, 'm3');
     DartType m4 = env.getMemberType(classA, 'm4');
     DartType m5 = env.getMemberType(classA, 'm5');
 
-    expect(true, A, function, expectMoreSpecific: false);
-    expect(true, A, m1, expectMoreSpecific: false);
+    expect(true, A, function);
+    expect(true, A, call);
+    expect(true, call, m1);
+    expect(true, A, m1);
     expect(true, A, m2, expectMoreSpecific: false);
     expect(false, A, m3);
     expect(false, A, m4);
-    expect(true, A, m5, expectMoreSpecific: false);
+    expect(true, A, m5);
   }));
 }