Program: 27994
Project: 27994
Buggy source:
/** 
 * An equivalence visitor.
 */
boolean checkEquivalenceHelper(JSType that,EquivalenceMethod eqMethod){
  if (this == that) {
    return true;
  }
  boolean thisUnknown=isUnknownType();
  boolean thatUnknown=that.isUnknownType();
  if (thisUnknown || thatUnknown) {
    if (eqMethod == EquivalenceMethod.INVARIANT) {
      return true;
    }
 else     if (eqMethod == EquivalenceMethod.DATA_FLOW) {
      return thisUnknown && thatUnknown;
    }
 else     if (thisUnknown && thatUnknown && (isNominalType() ^ that.isNominalType())) {
      return false;
    }
  }
  if (isUnionType() && that.isUnionType()) {
    return this.toMaybeUnionType().checkUnionEquivalenceHelper(that.toMaybeUnionType(),eqMethod);
  }
  if (isFunctionType() && that.isFunctionType()) {
    return this.toMaybeFunctionType().checkFunctionEquivalenceHelper(that.toMaybeFunctionType(),eqMethod);
  }
  if (isRecordType() && that.isRecordType()) {
    return this.toMaybeRecordType().checkRecordEquivalenceHelper(that.toMaybeRecordType(),eqMethod);
  }
  ParameterizedType thisParamType=toMaybeParameterizedType();
  ParameterizedType thatParamType=that.toMaybeParameterizedType();
  if (thisParamType != null || thatParamType != null) {
    boolean paramsMatch=false;
    if (thisParamType != null && thatParamType != null) {
      paramsMatch=thisParamType.getParameterType().checkEquivalenceHelper(thatParamType.getParameterType(),eqMethod);
    }
 else     if (eqMethod == EquivalenceMethod.IDENTITY) {
      paramsMatch=false;
    }
 else {
      paramsMatch=true;
    }
    JSType thisRootType=thisParamType == null ? this : thisParamType.getReferencedTypeInternal();
    JSType thatRootType=thatParamType == null ? that : thatParamType.getReferencedTypeInternal();
    return paramsMatch && thisRootType.checkEquivalenceHelper(thatRootType,eqMethod);
  }
  if (isNominalType() && that.isNominalType()) {
    return toObjectType().getReferenceName().equals(that.toObjectType().getReferenceName());
  }
  if (this instanceof ProxyObjectType) {
    return ((ProxyObjectType)this).getReferencedTypeInternal().checkEquivalenceHelper(that,eqMethod);
  }
  if (that instanceof ProxyObjectType) {
    return checkEquivalenceHelper(((ProxyObjectType)that).getReferencedTypeInternal(),eqMethod);
  }
  return this == that;
}

Fixed version (ground truth):
/** 
 * An equivalence visitor.
 */
boolean checkEquivalenceHelper(JSType that,EquivalenceMethod eqMethod){
  if (this == that) {
    return true;
  }
  boolean thisUnknown=isUnknownType();
  boolean thatUnknown=that.isUnknownType();
  if (thisUnknown || thatUnknown) {
    if (eqMethod == EquivalenceMethod.INVARIANT) {
      return true;
    }
 else     if (eqMethod == EquivalenceMethod.DATA_FLOW) {
      return thisUnknown && thatUnknown;
    }
 else     if (thisUnknown && thatUnknown && (isNominalType() ^ that.isNominalType())) {
      return false;
    }
  }
  if (isUnionType() && that.isUnionType()) {
    return toMaybeUnionType().checkUnionEquivalenceHelper(that.toMaybeUnionType(),eqMethod);
  }
  if (isFunctionType() && that.isFunctionType()) {
    return toMaybeFunctionType().checkFunctionEquivalenceHelper(that.toMaybeFunctionType(),eqMethod);
  }
  if (isRecordType() && that.isRecordType()) {
    return toMaybeRecordType().checkRecordEquivalenceHelper(that.toMaybeRecordType(),eqMethod);
  }
  ParameterizedType thisParamType=toMaybeParameterizedType();
  ParameterizedType thatParamType=that.toMaybeParameterizedType();
  if (thisParamType != null || thatParamType != null) {
    boolean paramsMatch=false;
    if (thisParamType != null && thatParamType != null) {
      paramsMatch=thisParamType.getParameterType().checkEquivalenceHelper(thatParamType.getParameterType(),eqMethod);
    }
 else     if (eqMethod == EquivalenceMethod.IDENTITY) {
      paramsMatch=false;
    }
 else {
      paramsMatch=true;
    }
    JSType thisRootType=thisParamType == null ? this : thisParamType.getReferencedTypeInternal();
    JSType thatRootType=thatParamType == null ? that : thatParamType.getReferencedTypeInternal();
    return paramsMatch && thisRootType.checkEquivalenceHelper(thatRootType,eqMethod);
  }
  if (isNominalType() && that.isNominalType()) {
    return toObjectType().getReferenceName().equals(that.toObjectType().getReferenceName());
  }
  if (this instanceof ProxyObjectType) {
    return ((ProxyObjectType)this).getReferencedTypeInternal().checkEquivalenceHelper(that,eqMethod);
  }
  if (that instanceof ProxyObjectType) {
    return checkEquivalenceHelper(((ProxyObjectType)that).getReferencedTypeInternal(),eqMethod);
  }
  return this == that;
}