@Override
 public JSType getType(StaticScope<JSType> scope, Node node, String prop) {
   if (node.getJSType() == null) {
     return registry.getNativeType(JSTypeNative.UNKNOWN_TYPE);
   }
   return node.getJSType();
 }
  /**
   * If we haven't found a return value yet, try to look at the "return" statements in the function.
   */
  FunctionTypeBuilder inferReturnStatementsAsLastResort(@Nullable Node functionBlock) {
    if (functionBlock == null || compiler.getInput(sourceName).isExtern()) {
      return this;
    }
    Preconditions.checkArgument(functionBlock.getType() == Token.BLOCK);
    if (returnType == null) {
      boolean hasNonEmptyReturns = false;
      List<Node> worklist = Lists.newArrayList(functionBlock);
      while (!worklist.isEmpty()) {
        Node current = worklist.remove(worklist.size() - 1);
        int cType = current.getType();
        if (cType == Token.RETURN && current.getFirstChild() != null || cType == Token.THROW) {
          hasNonEmptyReturns = true;
          break;
        } else if (NodeUtil.isStatementBlock(current) || NodeUtil.isControlStructure(current)) {
          for (Node child = current.getFirstChild(); child != null; child = child.getNext()) {
            worklist.add(child);
          }
        }
      }

      if (!hasNonEmptyReturns) {
        returnType = typeRegistry.getNativeType(VOID_TYPE);
        returnTypeInferred = true;
      }
    }
    return this;
  }
 public JSTypeSystem(AbstractCompiler compiler) {
   registry = compiler.getTypeRegistry();
   invalidatingTypes =
       Sets.newHashSet(
           registry.getNativeType(JSTypeNative.ALL_TYPE),
           registry.getNativeType(JSTypeNative.NO_OBJECT_TYPE),
           registry.getNativeType(JSTypeNative.NO_TYPE),
           registry.getNativeType(JSTypeNative.FUNCTION_PROTOTYPE),
           registry.getNativeType(JSTypeNative.FUNCTION_INSTANCE_TYPE),
           registry.getNativeType(JSTypeNative.OBJECT_PROTOTYPE),
           registry.getNativeType(JSTypeNative.TOP_LEVEL_PROTOTYPE),
           registry.getNativeType(JSTypeNative.UNKNOWN_TYPE));
 }
  public void testFunctionMismatch2() throws Exception {
    testSame(
        "/** \n"
            + " * @param {function(string): number} x \n"
            + " * @return {function(boolean): number} \n"
            + " */ function f(x) { return x; }",
        TYPE_MISMATCH_WARNING);

    JSTypeRegistry registry = compiler.getTypeRegistry();
    JSType string = registry.getNativeType(STRING_TYPE);
    JSType bool = registry.getNativeType(BOOLEAN_TYPE);
    JSType number = registry.getNativeType(NUMBER_TYPE);
    JSType firstFunction = registry.createFunctionType(number, string);
    JSType secondFunction = registry.createFunctionType(number, bool);

    assertMismatches(
        ImmutableList.of(
            new TypeMismatch(firstFunction, secondFunction, null),
            fromNatives(STRING_TYPE, BOOLEAN_TYPE)));
  }
  /**
   * Infer the parameter and return types of a function from the parameter and return types of the
   * function it is overriding.
   *
   * @param oldType The function being overridden. Does nothing if this is null.
   * @param paramsParent The LP node of the function that we're assigning to. If null, that just
   *     means we're not initializing this to a function literal.
   */
  FunctionTypeBuilder inferFromOverriddenFunction(
      @Nullable FunctionType oldType, @Nullable Node paramsParent) {
    if (oldType == null) {
      return this;
    }

    returnType = oldType.getReturnType();
    returnTypeInferred = oldType.isReturnTypeInferred();
    if (paramsParent == null) {
      // Not a function literal.
      parametersNode = oldType.getParametersNode();
      if (parametersNode == null) {
        parametersNode = new FunctionParamBuilder(typeRegistry).build();
      }
    } else {
      // We're overriding with a function literal. Apply type information
      // to each parameter of the literal.
      FunctionParamBuilder paramBuilder = new FunctionParamBuilder(typeRegistry);
      Iterator<Node> oldParams = oldType.getParameters().iterator();
      boolean warnedAboutArgList = false;
      boolean oldParamsListHitOptArgs = false;
      for (Node currentParam = paramsParent.getFirstChild();
          currentParam != null;
          currentParam = currentParam.getNext()) {
        if (oldParams.hasNext()) {
          Node oldParam = oldParams.next();
          Node newParam = paramBuilder.newParameterFromNode(oldParam);

          oldParamsListHitOptArgs =
              oldParamsListHitOptArgs || oldParam.isVarArgs() || oldParam.isOptionalArg();

          // The subclass method might right its var_args as individual
          // arguments.
          if (currentParam.getNext() != null && newParam.isVarArgs()) {
            newParam.setVarArgs(false);
            newParam.setOptionalArg(true);
          }
        } else {
          warnedAboutArgList |=
              addParameter(
                  paramBuilder,
                  typeRegistry.getNativeType(UNKNOWN_TYPE),
                  warnedAboutArgList,
                  codingConvention.isOptionalParameter(currentParam) || oldParamsListHitOptArgs,
                  codingConvention.isVarArgsParameter(currentParam));
        }
      }
      parametersNode = paramBuilder.build();
    }
    return this;
  }
  /** Builds the function type, and puts it in the registry. */
  FunctionType buildAndRegister() {
    if (returnType == null) {
      returnType = typeRegistry.getNativeType(UNKNOWN_TYPE);
    }

    if (parametersNode == null) {
      throw new IllegalStateException("All Function types must have params and a return type");
    }

    FunctionType fnType;
    if (isConstructor) {
      fnType = getOrCreateConstructor();
    } else if (isInterface) {
      fnType = typeRegistry.createInterfaceType(fnName, sourceNode);
      if (getScopeDeclaredIn().isGlobal() && !fnName.isEmpty()) {
        typeRegistry.declareType(fnName, fnType.getInstanceType());
      }
      maybeSetBaseType(fnType);
    } else {
      fnType =
          new FunctionBuilder(typeRegistry)
              .withName(fnName)
              .withSourceNode(sourceNode)
              .withParamsNode(parametersNode)
              .withReturnType(returnType, returnTypeInferred)
              .withTypeOfThis(thisType)
              .withTemplateName(templateTypeName)
              .build();
      maybeSetBaseType(fnType);
    }

    if (implementedInterfaces != null) {
      fnType.setImplementedInterfaces(implementedInterfaces);
    }

    typeRegistry.clearTemplateTypeName();

    return fnType;
  }
  /** Adds a basic set of properties to the native types. */
  public static void addNativeProperties(JSTypeRegistry registry) {
    JSType booleanType = registry.getNativeType(JSTypeNative.BOOLEAN_TYPE);
    JSType numberType = registry.getNativeType(JSTypeNative.NUMBER_TYPE);
    JSType stringType = registry.getNativeType(JSTypeNative.STRING_TYPE);
    JSType unknownType = registry.getNativeType(JSTypeNative.UNKNOWN_TYPE);

    ObjectType objectType = registry.getNativeObjectType(JSTypeNative.OBJECT_TYPE);
    ObjectType arrayType = registry.getNativeObjectType(JSTypeNative.ARRAY_TYPE);
    ObjectType dateType = registry.getNativeObjectType(JSTypeNative.DATE_TYPE);
    ObjectType regexpType = registry.getNativeObjectType(JSTypeNative.REGEXP_TYPE);
    ObjectType booleanObjectType = registry.getNativeObjectType(JSTypeNative.BOOLEAN_OBJECT_TYPE);
    ObjectType numberObjectType = registry.getNativeObjectType(JSTypeNative.NUMBER_OBJECT_TYPE);
    ObjectType stringObjectType = registry.getNativeObjectType(JSTypeNative.STRING_OBJECT_TYPE);

    ObjectType objectPrototype =
        registry.getNativeFunctionType(JSTypeNative.OBJECT_FUNCTION_TYPE).getPrototype();
    addMethod(registry, objectPrototype, "constructor", objectType);
    addMethod(registry, objectPrototype, "toString", stringType);
    addMethod(registry, objectPrototype, "toLocaleString", stringType);
    addMethod(registry, objectPrototype, "valueOf", unknownType);
    addMethod(registry, objectPrototype, "hasOwnProperty", booleanType);
    addMethod(registry, objectPrototype, "isPrototypeOf", booleanType);
    addMethod(registry, objectPrototype, "propertyIsEnumerable", booleanType);

    ObjectType arrayPrototype =
        registry.getNativeFunctionType(JSTypeNative.ARRAY_FUNCTION_TYPE).getPrototype();
    addMethod(registry, arrayPrototype, "constructor", arrayType);
    addMethod(registry, arrayPrototype, "toString", stringType);
    addMethod(registry, arrayPrototype, "toLocaleString", stringType);
    addMethod(registry, arrayPrototype, "concat", arrayType);
    addMethod(registry, arrayPrototype, "join", stringType);
    addMethod(registry, arrayPrototype, "pop", unknownType);
    addMethod(registry, arrayPrototype, "push", numberType);
    addMethod(registry, arrayPrototype, "reverse", arrayType);
    addMethod(registry, arrayPrototype, "shift", unknownType);
    addMethod(registry, arrayPrototype, "slice", arrayType);
    addMethod(registry, arrayPrototype, "sort", arrayType);
    addMethod(registry, arrayPrototype, "splice", arrayType);
    addMethod(registry, arrayPrototype, "unshift", numberType);
    arrayType.defineDeclaredProperty("length", numberType, true, null);

    ObjectType booleanPrototype =
        registry.getNativeFunctionType(JSTypeNative.BOOLEAN_OBJECT_FUNCTION_TYPE).getPrototype();
    addMethod(registry, booleanPrototype, "constructor", booleanObjectType);
    addMethod(registry, booleanPrototype, "toString", stringType);
    addMethod(registry, booleanPrototype, "valueOf", booleanType);

    ObjectType datePrototype =
        registry.getNativeFunctionType(JSTypeNative.DATE_FUNCTION_TYPE).getPrototype();
    addMethod(registry, datePrototype, "constructor", dateType);
    addMethod(registry, datePrototype, "toString", stringType);
    addMethod(registry, datePrototype, "toDateString", stringType);
    addMethod(registry, datePrototype, "toTimeString", stringType);
    addMethod(registry, datePrototype, "toLocaleString", stringType);
    addMethod(registry, datePrototype, "toLocaleDateString", stringType);
    addMethod(registry, datePrototype, "toLocaleTimeString", stringType);
    addMethod(registry, datePrototype, "valueOf", numberType);
    addMethod(registry, datePrototype, "getTime", numberType);
    addMethod(registry, datePrototype, "getFullYear", numberType);
    addMethod(registry, datePrototype, "getUTCFullYear", numberType);
    addMethod(registry, datePrototype, "getMonth", numberType);
    addMethod(registry, datePrototype, "getUTCMonth", numberType);
    addMethod(registry, datePrototype, "getDate", numberType);
    addMethod(registry, datePrototype, "getUTCDate", numberType);
    addMethod(registry, datePrototype, "getDay", numberType);
    addMethod(registry, datePrototype, "getUTCDay", numberType);
    addMethod(registry, datePrototype, "getHours", numberType);
    addMethod(registry, datePrototype, "getUTCHours", numberType);
    addMethod(registry, datePrototype, "getMinutes", numberType);
    addMethod(registry, datePrototype, "getUTCMinutes", numberType);
    addMethod(registry, datePrototype, "getSeconds", numberType);
    addMethod(registry, datePrototype, "getUTCSeconds", numberType);
    addMethod(registry, datePrototype, "getMilliseconds", numberType);
    addMethod(registry, datePrototype, "getUTCMilliseconds", numberType);
    addMethod(registry, datePrototype, "getTimezoneOffset", numberType);
    addMethod(registry, datePrototype, "setTime", numberType);
    addMethod(registry, datePrototype, "setMilliseconds", numberType);
    addMethod(registry, datePrototype, "setUTCMilliseconds", numberType);
    addMethod(registry, datePrototype, "setSeconds", numberType);
    addMethod(registry, datePrototype, "setUTCSeconds", numberType);
    addMethod(registry, datePrototype, "setMinutes", numberType);
    addMethod(registry, datePrototype, "setUTCMinutes", numberType);
    addMethod(registry, datePrototype, "setHours", numberType);
    addMethod(registry, datePrototype, "setUTCHours", numberType);
    addMethod(registry, datePrototype, "setDate", numberType);
    addMethod(registry, datePrototype, "setUTCDate", numberType);
    addMethod(registry, datePrototype, "setMonth", numberType);
    addMethod(registry, datePrototype, "setUTCMonth", numberType);
    addMethod(registry, datePrototype, "setFullYear", numberType);
    addMethod(registry, datePrototype, "setUTCFullYear", numberType);
    addMethod(registry, datePrototype, "toUTCString", stringType);
    addMethod(registry, datePrototype, "toGMTString", stringType);

    ObjectType numberPrototype =
        registry.getNativeFunctionType(JSTypeNative.NUMBER_OBJECT_FUNCTION_TYPE).getPrototype();
    addMethod(registry, numberPrototype, "constructor", numberObjectType);
    addMethod(registry, numberPrototype, "toString", stringType);
    addMethod(registry, numberPrototype, "toLocaleString", stringType);
    addMethod(registry, numberPrototype, "valueOf", numberType);
    addMethod(registry, numberPrototype, "toFixed", stringType);
    addMethod(registry, numberPrototype, "toExponential", stringType);
    addMethod(registry, numberPrototype, "toPrecision", stringType);

    ObjectType regexpPrototype =
        registry.getNativeFunctionType(JSTypeNative.REGEXP_FUNCTION_TYPE).getPrototype();
    addMethod(registry, regexpPrototype, "constructor", regexpType);
    addMethod(registry, regexpPrototype, "exec", registry.createNullableType(arrayType));
    addMethod(registry, regexpPrototype, "test", booleanType);
    addMethod(registry, regexpPrototype, "toString", stringType);
    regexpType.defineDeclaredProperty("source", stringType, true, null);
    regexpType.defineDeclaredProperty("global", booleanType, true, null);
    regexpType.defineDeclaredProperty("ignoreCase", booleanType, true, null);
    regexpType.defineDeclaredProperty("multiline", booleanType, true, null);
    regexpType.defineDeclaredProperty("lastIndex", numberType, true, null);

    ObjectType stringPrototype =
        registry.getNativeFunctionType(JSTypeNative.STRING_OBJECT_FUNCTION_TYPE).getPrototype();
    addMethod(registry, stringPrototype, "constructor", stringObjectType);
    addMethod(registry, stringPrototype, "toString", stringType);
    addMethod(registry, stringPrototype, "valueOf", stringType);
    addMethod(registry, stringPrototype, "charAt", stringType);
    addMethod(registry, stringPrototype, "charCodeAt", numberType);
    addMethod(registry, stringPrototype, "concat", stringType);
    addMethod(registry, stringPrototype, "indexOf", numberType);
    addMethod(registry, stringPrototype, "lastIndexOf", numberType);
    addMethod(registry, stringPrototype, "localeCompare", numberType);
    addMethod(registry, stringPrototype, "match", registry.createNullableType(arrayType));
    addMethod(registry, stringPrototype, "replace", stringType);
    addMethod(registry, stringPrototype, "search", numberType);
    addMethod(registry, stringPrototype, "slice", stringType);
    addMethod(registry, stringPrototype, "split", arrayType);
    addMethod(registry, stringPrototype, "substring", stringType);
    addMethod(registry, stringPrototype, "toLowerCase", stringType);
    addMethod(registry, stringPrototype, "toLocaleLowerCase", stringType);
    addMethod(registry, stringPrototype, "toUpperCase", stringType);
    addMethod(registry, stringPrototype, "toLocaleUpperCase", stringType);
    stringObjectType.defineDeclaredProperty("length", numberType, true, null);
  }
  protected void initTypes() {
    ALL_TYPE = registry.getNativeType(JSTypeNative.ALL_TYPE);
    NO_OBJECT_TYPE = registry.getNativeObjectType(JSTypeNative.NO_OBJECT_TYPE);
    NO_TYPE = registry.getNativeObjectType(JSTypeNative.NO_TYPE);
    NO_RESOLVED_TYPE = registry.getNativeObjectType(JSTypeNative.NO_RESOLVED_TYPE);
    ARRAY_FUNCTION_TYPE = registry.getNativeType(JSTypeNative.ARRAY_FUNCTION_TYPE);
    ARRAY_TYPE = registry.getNativeObjectType(JSTypeNative.ARRAY_TYPE);
    BOOLEAN_OBJECT_FUNCTION_TYPE =
        registry.getNativeType(JSTypeNative.BOOLEAN_OBJECT_FUNCTION_TYPE);
    BOOLEAN_OBJECT_TYPE = registry.getNativeObjectType(JSTypeNative.BOOLEAN_OBJECT_TYPE);
    BOOLEAN_TYPE = registry.getNativeType(JSTypeNative.BOOLEAN_TYPE);
    CHECKED_UNKNOWN_TYPE = registry.getNativeType(JSTypeNative.CHECKED_UNKNOWN_TYPE);
    DATE_FUNCTION_TYPE = registry.getNativeType(JSTypeNative.DATE_FUNCTION_TYPE);
    DATE_TYPE = registry.getNativeObjectType(JSTypeNative.DATE_TYPE);
    ERROR_FUNCTION_TYPE = registry.getNativeType(JSTypeNative.ERROR_FUNCTION_TYPE);
    ERROR_TYPE = registry.getNativeObjectType(JSTypeNative.ERROR_TYPE);
    EVAL_ERROR_FUNCTION_TYPE = registry.getNativeType(JSTypeNative.EVAL_ERROR_FUNCTION_TYPE);
    EVAL_ERROR_TYPE = registry.getNativeObjectType(JSTypeNative.EVAL_ERROR_TYPE);
    FUNCTION_FUNCTION_TYPE = registry.getNativeFunctionType(JSTypeNative.FUNCTION_FUNCTION_TYPE);
    FUNCTION_INSTANCE_TYPE = registry.getNativeFunctionType(JSTypeNative.FUNCTION_INSTANCE_TYPE);
    FUNCTION_PROTOTYPE = registry.getNativeObjectType(JSTypeNative.FUNCTION_PROTOTYPE);
    GREATEST_FUNCTION_TYPE = registry.getNativeType(JSTypeNative.GREATEST_FUNCTION_TYPE);
    LEAST_FUNCTION_TYPE = registry.getNativeType(JSTypeNative.LEAST_FUNCTION_TYPE);
    NULL_TYPE = registry.getNativeType(JSTypeNative.NULL_TYPE);
    NUMBER_OBJECT_FUNCTION_TYPE = registry.getNativeType(JSTypeNative.NUMBER_OBJECT_FUNCTION_TYPE);
    NUMBER_OBJECT_TYPE = registry.getNativeObjectType(JSTypeNative.NUMBER_OBJECT_TYPE);
    NUMBER_STRING_BOOLEAN = registry.getNativeType(JSTypeNative.NUMBER_STRING_BOOLEAN);
    NUMBER_TYPE = registry.getNativeType(JSTypeNative.NUMBER_TYPE);
    OBJECT_FUNCTION_TYPE = registry.getNativeFunctionType(JSTypeNative.OBJECT_FUNCTION_TYPE);
    OBJECT_NUMBER_STRING = registry.getNativeType(JSTypeNative.OBJECT_NUMBER_STRING);
    OBJECT_NUMBER_STRING_BOOLEAN =
        registry.getNativeType(JSTypeNative.OBJECT_NUMBER_STRING_BOOLEAN);
    OBJECT_PROTOTYPE = registry.getNativeType(JSTypeNative.OBJECT_PROTOTYPE);
    OBJECT_TYPE = registry.getNativeObjectType(JSTypeNative.OBJECT_TYPE);
    RANGE_ERROR_FUNCTION_TYPE = registry.getNativeType(JSTypeNative.RANGE_ERROR_FUNCTION_TYPE);
    RANGE_ERROR_TYPE = registry.getNativeObjectType(JSTypeNative.RANGE_ERROR_TYPE);
    REFERENCE_ERROR_FUNCTION_TYPE =
        registry.getNativeType(JSTypeNative.REFERENCE_ERROR_FUNCTION_TYPE);
    REFERENCE_ERROR_TYPE = registry.getNativeObjectType(JSTypeNative.REFERENCE_ERROR_TYPE);
    REGEXP_FUNCTION_TYPE = registry.getNativeType(JSTypeNative.REGEXP_FUNCTION_TYPE);
    REGEXP_TYPE = registry.getNativeObjectType(JSTypeNative.REGEXP_TYPE);
    STRING_OBJECT_FUNCTION_TYPE = registry.getNativeType(JSTypeNative.STRING_OBJECT_FUNCTION_TYPE);
    STRING_OBJECT_TYPE = registry.getNativeObjectType(JSTypeNative.STRING_OBJECT_TYPE);
    STRING_TYPE = registry.getNativeType(JSTypeNative.STRING_TYPE);
    SYNTAX_ERROR_FUNCTION_TYPE = registry.getNativeType(JSTypeNative.SYNTAX_ERROR_FUNCTION_TYPE);
    SYNTAX_ERROR_TYPE = registry.getNativeObjectType(JSTypeNative.SYNTAX_ERROR_TYPE);
    TYPE_ERROR_FUNCTION_TYPE = registry.getNativeType(JSTypeNative.TYPE_ERROR_FUNCTION_TYPE);
    TYPE_ERROR_TYPE = registry.getNativeObjectType(JSTypeNative.TYPE_ERROR_TYPE);
    U2U_CONSTRUCTOR_TYPE = registry.getNativeFunctionType(JSTypeNative.U2U_CONSTRUCTOR_TYPE);
    U2U_FUNCTION_TYPE = registry.getNativeFunctionType(JSTypeNative.U2U_FUNCTION_TYPE);
    UNKNOWN_TYPE = registry.getNativeObjectType(JSTypeNative.UNKNOWN_TYPE);
    URI_ERROR_FUNCTION_TYPE = registry.getNativeType(JSTypeNative.URI_ERROR_FUNCTION_TYPE);
    URI_ERROR_TYPE = registry.getNativeObjectType(JSTypeNative.URI_ERROR_TYPE);
    VOID_TYPE = registry.getNativeType(JSTypeNative.VOID_TYPE);

    addNativeProperties(registry);

    NATIVE_PROPERTIES_COUNT = OBJECT_TYPE.getPropertiesCount();
  }
  /** Infer the parameter types from the list of argument names and the doc info. */
  FunctionTypeBuilder inferParameterTypes(@Nullable Node argsParent, @Nullable JSDocInfo info) {
    if (argsParent == null) {
      if (info == null) {
        return this;
      } else {
        return inferParameterTypes(info);
      }
    }

    // arguments
    Node oldParameterType = null;
    if (parametersNode != null) {
      oldParameterType = parametersNode.getFirstChild();
    }

    FunctionParamBuilder builder = new FunctionParamBuilder(typeRegistry);
    boolean warnedAboutArgList = false;
    Set<String> allJsDocParams =
        (info == null) ? Sets.<String>newHashSet() : Sets.newHashSet(info.getParameterNames());
    boolean foundTemplateType = false;
    for (Node arg : argsParent.children()) {
      String argumentName = arg.getString();
      allJsDocParams.remove(argumentName);

      // type from JSDocInfo
      JSType parameterType = null;
      boolean isOptionalParam = isOptionalParameter(arg, info);
      boolean isVarArgs = isVarArgsParameter(arg, info);
      if (info != null && info.hasParameterType(argumentName)) {
        parameterType = info.getParameterType(argumentName).evaluate(scope, typeRegistry);
      } else if (oldParameterType != null && oldParameterType.getJSType() != null) {
        parameterType = oldParameterType.getJSType();
        isOptionalParam = oldParameterType.isOptionalArg();
        isVarArgs = oldParameterType.isVarArgs();
      } else {
        parameterType = typeRegistry.getNativeType(UNKNOWN_TYPE);
      }

      if (templateTypeName != null
          && parameterType.restrictByNotNullOrUndefined().isTemplateType()) {
        if (foundTemplateType) {
          reportError(TEMPLATE_TYPE_DUPLICATED, fnName);
        }
        foundTemplateType = true;
      }
      warnedAboutArgList |=
          addParameter(builder, parameterType, warnedAboutArgList, isOptionalParam, isVarArgs);

      if (oldParameterType != null) {
        oldParameterType = oldParameterType.getNext();
      }
    }

    if (templateTypeName != null && !foundTemplateType) {
      reportError(TEMPLATE_TYPE_EXPECTED, fnName);
    }

    for (String inexistentName : allJsDocParams) {
      reportWarning(INEXISTANT_PARAM, inexistentName, fnName);
    }

    parametersNode = builder.build();
    return this;
  }
 private TypeMismatch fromNatives(JSTypeNative a, JSTypeNative b) {
   JSTypeRegistry registry = compiler.getTypeRegistry();
   return new TypeMismatch(registry.getNativeType(a), registry.getNativeType(b), null);
 }