anchor.diff:        }
       }
       return true;
  +  }
  +
  +  /**
  +   * Invokes [callback] for each parameter of [kind] with the parameter's [name]
  +   * and [type] after any type parameters have been applied.
  +   */
  +  void _forEachParameterType(
  +      ParameterKind kind, callback(String name, DartType type)) {
  +    if (baseParameters.isEmpty) {
  +      return;
  +    }
  +
  +    List<DartType> typeParameters =
  +        TypeParameterTypeImpl.getTypes(this.typeParameters);
  +    for (ParameterElement parameter in baseParameters) {
  +      if (parameter.parameterKind == kind) {
  +        TypeImpl type = parameter.type;
  +        if (typeArguments.length != 0 &&
  +            typeArguments.length == typeParameters.length) {
  +          type = type.substitute2(typeArguments, typeParameters, newPrune);
  +        } else {
  +          type = type.pruned(newPrune);
  +        }
  +
  +        callback(parameter.name, type);
  +      }
  +    }
     }
   }
   
  
positive.code:     } else if (this == type) {
        return true;
      }
      FunctionType t = this;
      FunctionType s = type as FunctionType;
      List<DartType> tTypes = t.normalParameterTypes;
      List<DartType> tOpTypes = t.optionalParameterTypes;
      List<DartType> sTypes = s.normalParameterTypes;
      List<DartType> sOpTypes = s.optionalParameterTypes;
      // If one function has positional and the other has named parameters,
      // return false.
      if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) ||
          (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) {
        return false;
      }
      // named parameters case
      if (t.namedParameterTypes.length > 0) {
        // check that the number of required parameters are equal, and check that
        // every t_i is more specific than every s_i
        if (t.normalParameterTypes.length != s.normalParameterTypes.length) {
          return false;
        } else if (t.normalParameterTypes.length > 0) {
          for (int i = 0; i < tTypes.length; i++) {
            if (!(tTypes[i] as TypeImpl)
                .isMoreSpecificThan(sTypes[i], withDynamic)) {
              return false;
            }
          }
        }
        Map<String, DartType> namedTypesT = t.namedParameterTypes;
        Map<String, DartType> namedTypesS = s.namedParameterTypes;
        // if k >= m is false, return false: the passed function type has more
        // named parameter types than this
        if (namedTypesT.length < namedTypesS.length) {
          return false;
        }
        // Loop through each element in S verifying that T has a matching
        // parameter name and that the corresponding type is more specific then
        // the type in S.
        for (String keyS in namedTypesS.keys) {
          DartType typeT = namedTypesT[keyS];
          if (typeT == null) {
            return false;
          }
          if (!(typeT as TypeImpl)
              .isMoreSpecificThan(namedTypesS[keyS], withDynamic)) {
            return false;
          }
        }
      } else if (s.namedParameterTypes.length > 0) {
        return false;
      } else {
        // positional parameter case
        int tArgLength = tTypes.length + tOpTypes.length;
        int sArgLength = sTypes.length + sOpTypes.length;
        // Check that the total number of parameters in t is greater than or equal
        // to the number of parameters in s and that the number of required
        // parameters in s is greater than or equal to the number of required
        // parameters in t.
        if (tArgLength < sArgLength || sTypes.length < tTypes.length) {
          return false;
        }
        if (tOpTypes.length == 0 && sOpTypes.length == 0) {
          // No positional arguments, don't copy contents to new array
          for (int i = 0; i < sTypes.length; i++) {
            if (!(tTypes[i] as TypeImpl)
                .isMoreSpecificThan(sTypes[i], withDynamic)) {
              return false;
            }
          }
        } else {
          // Else, we do have positional parameters, copy required and positional
          // parameter types into arrays to do the compare (for loop below).
          List<DartType> tAllTypes = new List<DartType>(sArgLength);
          for (int i = 0; i < tTypes.length; i++) {
            tAllTypes[i] = tTypes[i];
          }
          for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) {
            tAllTypes[i] = tOpTypes[j];
          }
          List<DartType> sAllTypes = new List<DartType>(sArgLength);
          for (int i = 0; i < sTypes.length; i++) {
            sAllTypes[i] = sTypes[i];
          }
          for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) {
            sAllTypes[i] = sOpTypes[j];
          }
          for (int i = 0; i < sAllTypes.length; i++) {
            if (!(tAllTypes[i] as TypeImpl)
                .isMoreSpecificThan(sAllTypes[i], withDynamic)) {
              return false;
            }
          }
        }
      }
      DartType tRetType = t.returnType;
      DartType sRetType = s.returnType;
      return sRetType.isVoid ||
          (tRetType as TypeImpl).isMoreSpecificThan(sRetType, withDynamic);
    }
  
    @override
    bool isSubtypeOf(DartType type) {
      // trivial base cases
      if (type == null) {
        return false;
      } else if (identical(this, type) ||
          type.isDynamic ||
          type.isDartCoreFunction ||
          type.isObject) {
        return true;
      } else if (type is! FunctionType) {
        return false;
      } else if (this == type) {
        return true;
      }
      FunctionType t = this;
      FunctionType s = type as FunctionType;
      List<DartType> tTypes = t.normalParameterTypes;
      List<DartType> tOpTypes = t.optionalParameterTypes;
      List<DartType> sTypes = s.normalParameterTypes;
      List<DartType> sOpTypes = s.optionalParameterTypes;
      // If one function has positional and the other has named parameters,
      // return false.
      if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) ||
          (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) {
        return false;
      }
      // named parameters case
      if (t.namedParameterTypes.length > 0) {
        // check that the number of required parameters are equal,
        // and check that every t_i is assignable to every s_i
        if (t.normalParameterTypes.length != s.normalParameterTypes.length) {
          return false;
        } else if (t.normalParameterTypes.length > 0) {
          for (int i = 0; i < tTypes.length; i++) {
            if (!(tTypes[i] as TypeImpl).isAssignableTo(sTypes[i])) {
              return false;
            }
          }
        }
        Map<String, DartType> namedTypesT = t.namedParameterTypes;
        Map<String, DartType> namedTypesS = s.namedParameterTypes;
        // if k >= m is false, return false: the passed function type has more
        // named parameter types than this
        if (namedTypesT.length < namedTypesS.length) {
          return false;
        }
        // Loop through each element in S verifying that T has a matching
        // parameter name and that the corresponding type is assignable to the
        // type in S.
        for (String keyS in namedTypesS.keys) {
          DartType typeT = namedTypesT[keyS];
          if (typeT == null) {
            return false;
          }
          if (!(typeT as TypeImpl).isAssignableTo(namedTypesS[keyS])) {
            return false;
          }
        }
      } else if (s.namedParameterTypes.length > 0) {
        return false;
      } else {
        // positional parameter case
        int tArgLength = tTypes.length + tOpTypes.length;
        int sArgLength = sTypes.length + sOpTypes.length;
        // Check that the total number of parameters in t is greater than or
        // equal to the number of parameters in s and that the number of
        // required parameters in s is greater than or equal to the number of
        // required parameters in t.
        if (tArgLength < sArgLength || sTypes.length < tTypes.length) {
          return false;
        }
        if (tOpTypes.length == 0 && sOpTypes.length == 0) {
          // No positional arguments, don't copy contents to new array
          for (int i = 0; i < sTypes.length; i++) {
            if (!(tTypes[i] as TypeImpl).isAssignableTo(sTypes[i])) {
              return false;
            }
          }
        } else {
          // Else, we do have positional parameters, copy required and
          // positional parameter types into arrays to do the compare (for loop
          // below).
          List<DartType> tAllTypes = new List<DartType>(sArgLength);
          for (int i = 0; i < tTypes.length; i++) {
            tAllTypes[i] = tTypes[i];
          }
          for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) {
            tAllTypes[i] = tOpTypes[j];
          }
          List<DartType> sAllTypes = new List<DartType>(sArgLength);
          for (int i = 0; i < sTypes.length; i++) {
            sAllTypes[i] = sTypes[i];
          }
          for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) {
            sAllTypes[i] = sOpTypes[j];
          }
          for (int i = 0; i < sAllTypes.length; i++) {
            if (!(tAllTypes[i] as TypeImpl).isAssignableTo(sAllTypes[i])) {
              return false;
            }
          }
        }
      }
      DartType tRetType = t.returnType;
      DartType sRetType = s.returnType;
      return sRetType.isVoid || (tRetType as TypeImpl).isAssignableTo(sRetType);
    }
  
    @override
  
negative.code: 
    @override
    List<DartType> get normalParameterTypes {
      List<DartType> types = <DartType>[];
      _forEachParameterType(ParameterKind.REQUIRED, (name, type) {
        types.add(type);
      });
      return types;
    }
  
  