anchor.diff:        return true;
       } else {
         // Check [s] <: Future<T>.
  -      // TODO(fishythefish): Do this without allocating an RTI for Future<T>
  -      // each time.
         String futureClass = JS_GET_NAME(JsGetName.FUTURE_CLASS_TYPE_NAME);
         var argumentsArray = JS('', '[#]', tTypeArgument);
  -      var tFuture =
  -          _Universe._lookupInterfaceRti(universe, futureClass, argumentsArray);
  -      return _isSubtype(universe, s, sEnv, tFuture, tEnv);
  -    }
  -  }
  -
  +      return _isSubtypeOfInterface(
  +          universe, s, sEnv, futureClass, argumentsArray, tEnv);
  +    }
  +  }
  +
  +  assert(Rti._getKind(t) == Rti.kindInterface);
  +  String tName = Rti._getInterfaceName(t);
  +  var tArgs = Rti._getInterfaceTypeArguments(t);
  +
  +  return _isSubtypeOfInterface(universe, s, sEnv, tName, tArgs, tEnv);
  +}
  +
  +bool _isSubtypeOfInterface(
  +    universe, Rti s, sEnv, String tName, Object tArgs, tEnv) {
     assert(Rti._getKind(s) == Rti.kindInterface);
  -  assert(Rti._getKind(t) == Rti.kindInterface);
     String sName = Rti._getInterfaceName(s);
  -  String tName = Rti._getInterfaceName(t);
   
     if (sName == tName) {
       var sArgs = Rti._getInterfaceTypeArguments(s);
  -    var tArgs = Rti._getInterfaceTypeArguments(t);
       int length = _Utils.arrayLength(sArgs);
       assert(length == _Utils.arrayLength(tArgs));
       for (int i = 0; i < length; i++) {
  
positive.code:   return _isSubtype(universe, s, null, t, null);
  }
  
  bool _isSubtype(universe, Rti s, var sEnv, Rti t, var tEnv) {
    // TODO(fishythefish): Update for NNBD. See
    // https://github.com/dart-lang/language/blob/master/resources/type-system/subtyping.md#rules
  
  
negative.code:   if (rule == null) return false;
    var supertypeArgs = TypeRule.lookupSupertype(rule, tName);
    if (supertypeArgs == null) return false;
    int length = _Utils.arrayLength(supertypeArgs);
    assert(length == _Utils.arrayLength(tArgs));
    for (int i = 0; i < length; i++) {
  