anchor.diff:      throw new ArgumentError('Cannot extract type of null instance.');
     }
     var type = unwrapType(T);
  -  if (type is AbstractFunctionType) {
  +  if (type is AbstractFunctionType || _isFutureOr(type)) {
       throw new ArgumentError('Cannot extract from non-class type ($type).');
     }
  -  List typeArgs = _extractTypes(getReifiedType(instance), type);
  +  var typeArguments = getGenericArgs(type);
  +  if (typeArguments.isEmpty) {
  +    throw new ArgumentError('Cannot extract from non-generic type ($type).');
  +  }
  +  List typeArgs = _extractTypes(getReifiedType(instance), type, typeArguments);
  +  // The signature of this method guarantees that instance is a T, so we
  +  // should have a valid non-empty list at this point.
  +  assert(typeArgs != null && typeArgs.isNotEmpty);
     return _checkAndCall(
         f, _getRuntimeType(f), JS('', 'void 0'), typeArgs, [], 'call');
   }
  
positive.code:   let getInterfaces = $getImplements($t1);
    if (getInterfaces) {
      for (let i1 of getInterfaces()) {
        result = $_extractTypes(i1, $t2);
        if (result) return result;
      }
    }
  
negative.code:   if (raw1 != null && raw1 == raw2) {
      let typeArguments1 = $getGenericArgs($t1);
      let length = typeArguments1.length;
      if (length == 0 || length != typeArguments2.length) $assertFailed();
      // TODO(vsm): Remove this subtyping check if/when we eliminate the ability
      // to implement multiple versions of the same interface
      // (e.g., Foo<int>, Foo<String>).
      for (let i = 0; i < length; ++i) {
        let result =
            $_isSubtype(typeArguments1[i], typeArguments2[i], true);
  