Program: 50507
Project: 50507
Buggy source:
public Type analyze(AstNode node,TypeScope env,Set<Type> nonGen){
  int id=_id++;
  if (node instanceof Program) {
    for (    Instruction inst : ((Program)node).instructions) {
      if (inst instanceof LetBinding) {
        LetBinding let=(LetBinding)inst;
        if (let.args.size() > 0) {
          env.define(let.name,Type.Function(new Type.Variable(),new Type.Variable()));
        }
      }
    }
    for (    Instruction inst : ((Program)node).instructions) {
      try {
        Type type=analyze(inst,env,nonGen);
      }
 catch (      TypeError e) {
        System.err.println("String_Node_Str" + env);
        throw new RuntimeException("String_Node_Str" + inst,e);
      }
    }
    return null;
  }
 else   if (node instanceof Expr.ENum) {
    return Type.INT;
  }
 else   if (node instanceof Expr.EBool) {
    return Type.BOOL;
  }
 else   if (node instanceof Expr.EStr) {
    return Type.STR;
  }
 else   if (node instanceof Expr.EChar) {
    return Type.CHAR;
  }
 else   if (node == Expr.EUnit) {
    return Type.UNIT;
  }
 else   if (node instanceof Expr.EList) {
    Type valueType=new Type.Variable();
    for (    Expr expr : ((Expr.EList)node).values) {
      unify(valueType,analyze(expr,env,nonGen));
    }
    return Type.List(valueType);
  }
 else   if (node instanceof Expr.ETuple) {
    List<Type> valuesTypes=new ArrayList<Type>();
    for (    Expr expr : ((Expr.ETuple)node).values) {
      valuesTypes.add(analyze(expr,env,nonGen));
    }
    return Type.Product(valuesTypes);
  }
 else   if (node instanceof Expr.ERecord) {
    Expr.ERecord rec=(Expr.ERecord)node;
    Map<String,Type> valuesTypes=new HashMap<String,Type>();
    for (    Map.Entry<String,Expr> entry : rec.values.entrySet()) {
      valuesTypes.put(entry.getKey(),analyze(entry.getValue(),env,nonGen));
    }
    return new Type.RecordType(valuesTypes);
  }
 else   if (node instanceof Expr.EName) {
    return getType(((Expr.EName)node).name,env,nonGen);
  }
 else   if (node instanceof Expr.EAccessor) {
    Expr.EAccessor acc=(Expr.EAccessor)node;
    Type objType=analyze(acc.obj,env,nonGen);
    Type.Variable res=new Type.Variable();
    Type.RecordType desiredType=new Type.RecordType(Collections.<String,Type>singletonMap(acc.field,res));
    unify(objType,desiredType);
    return res;
  }
 else   if (node instanceof Expr.EAp) {
    Expr.EAp ap=(Expr.EAp)node;
    Type funcType=analyze(ap.fn,env,nonGen);
    Type argType=analyze(ap.arg,env,nonGen);
    Type.Variable resType=new Type.Variable();
    try {
      unify(Type.Function(argType,resType),funcType);
    }
 catch (    TypeError e) {
      throw new TypeError("String_Node_Str" + ap,Type.Function(argType,resType),funcType,e);
    }
    return resType;
  }
 else   if (node instanceof Expr.EIf) {
    Expr.EIf eif=(Expr.EIf)node;
    Type condType=analyze(eif.cond,env,nonGen);
    if (!isException(condType)) {
      unify(condType,Type.BOOL);
    }
    Type thenType=null;
    for (    Instruction instr : eif.thenInstructions) {
      thenType=analyze(instr,env,nonGen);
    }
    Type elseType=null;
    for (    Instruction instr : eif.elseInstructions) {
      elseType=analyze(instr,env,nonGen);
    }
    if (!isException(thenType) && !isException(elseType)) {
      unify(thenType,elseType);
    }
    return isException(thenType) ? elseType : thenType;
  }
 else   if (node instanceof Expr.PatterMatching) {
    Expr.PatterMatching patmat=(Expr.PatterMatching)node;
    Type inputType=analyze(patmat.input,env,nonGen);
    Type resType=new Type.Variable();
    boolean allExceptions=true;
    for (    Expr.PatterMatching.Case pcase : patmat.cases) {
      TypeScope newScope=env.child();
      Type patType=visit(pcase.pattern,newScope,nonGen);
      if (!isException(inputType)) {
        unify(patType,inputType);
      }
      Type caseType=null;
      for (      Instruction instruction : pcase.outcome) {
        caseType=analyze(instruction,newScope,nonGen);
      }
      if (!isException(caseType)) {
        unify(caseType,resType);
        resType=caseType;
        allExceptions=false;
      }
    }
    return allExceptions ? Type.EXCEPTION : resType;
  }
 else   if (node instanceof Expr.EThrow) {
    Expr.EThrow ethrow=(Expr.EThrow)node;
    Type exType=analyze(ethrow.exception,env);
    unify(exType,Type.EXCEPTION);
    return Type.EXCEPTION;
  }
 else   if (node instanceof Expr.TryCatch) {
    Expr.TryCatch tc=(Expr.TryCatch)node;
    Type tryType=null;
    for (    Instruction instr : tc.tryBody) {
      tryType=analyze(instr,env,nonGen);
    }
    tryType=prune(tryType);
    System.err.println("String_Node_Str" + tryType.getClass());
    System.err.println("String_Node_Str" + (tryType == Type.EXCEPTION));
    Type.Variable resType=new Type.Variable();
    if (!isException(tryType)) {
      System.err.println("String_Node_Str");
      unify(tryType,resType);
    }
    for (    Expr.PatterMatching.Case pcase : tc.catchCases) {
      TypeScope newScope=env.child();
      Type patType=visit(pcase.pattern,newScope,nonGen);
      unify(patType,Type.EXCEPTION);
      Type caseType=null;
      for (      Instruction instruction : pcase.outcome) {
        caseType=analyze(instruction,newScope,nonGen);
      }
      unify(caseType,resType);
    }
    return resType;
  }
 else   if (node instanceof Expr.ELam) {
    Expr.ELam lam=(Expr.ELam)node;
    TypeScope newEnv=env.child();
    Set<Type> newNonGen=new HashSet<Type>(nonGen);
    List<Type> argTypes=new ArrayList<Type>();
    for (    Named arg : lam.args) {
      Type argType=new Type.Variable();
      argTypes.add(argType);
      newEnv.define(arg.name,argType);
      newNonGen.add(argType);
    }
    Type resultType=null;
    for (    Instruction instr : lam.instructions) {
      resultType=analyze(instr,newEnv,newNonGen);
    }
    if (lam.type != null) {
      unify(resultType,lam.type);
    }
    return Type.Function(argTypes,resultType);
  }
 else   if (node instanceof LetBinding) {
    LetBinding let=(LetBinding)node;
    TypeScope newEnv=env.child();
    Set<Type> newNonGen=new HashSet<Type>(nonGen);
    List<Type> argTypes=new ArrayList<Type>();
    Type.Variable letTypeVar=new Type.Variable();
    newEnv.define(let.name,letTypeVar);
    newNonGen.add(letTypeVar);
    for (    Named arg : let.args) {
      Type argType=new Type.Variable();
      argTypes.add(argType);
      newEnv.define(arg.name,argType);
      newNonGen.add(argType);
    }
    Type resultType=null;
    for (    Instruction instr : let.instructions) {
      resultType=analyze(instr,newEnv,newNonGen);
    }
    if (let.type != null) {
      unify(resultType,let.type);
    }
    Type letType=Type.Function(argTypes,resultType);
    env.define(let.name,letType);
    return letType;
  }
 else   if (node instanceof DestructuringLetBinding) {
    DestructuringLetBinding let=(DestructuringLetBinding)node;
    TypeScope newEnv=env.child();
    Set<Type> newNonGen=new HashSet<Type>(nonGen);
    List<Type> argTypes=new ArrayList<Type>();
    Type letTypeVar=visit(let.main,newEnv,newNonGen);
    newNonGen.add(letTypeVar);
    for (    Pattern arg : let.args) {
      Type argType=visit(arg,newEnv,newNonGen);
      argTypes.add(argType);
    }
    Type resultType=null;
    for (    Instruction instr : let.instructions) {
      resultType=analyze(instr,newEnv,newNonGen);
    }
    Type letType=Type.Function(argTypes,resultType);
    define(let.main,letType,env);
    return letType;
  }
 else   if (node instanceof DataDecl) {
    DataDecl dataDecl=(DataDecl)node;
    for (    DataDecl.TypeConstructor tyCon : dataDecl.typeConstructors) {
      env.define(tyCon.name,Type.TyCon(tyCon,dataDecl));
    }
    return dataDecl.type;
  }
 else   if (node instanceof ExceptionDecl) {
    ExceptionDecl dataDecl=(ExceptionDecl)node;
    env.define(dataDecl.name,new Type.ExceptionCon(dataDecl.name,dataDecl.types));
    return Type.EXCEPTION;
  }
 else {
    throw new RuntimeException("String_Node_Str" + node.getClass());
  }
}

Fixed version (ground truth):
public Type analyze(AstNode node,TypeScope env,Set<Type> nonGen){
  int id=_id++;
  if (node instanceof Program) {
    for (    Instruction inst : ((Program)node).instructions) {
      if (inst instanceof LetBinding) {
        LetBinding let=(LetBinding)inst;
        if (let.args.size() > 0) {
          env.define(let.name,Type.Function(new Type.Variable(),new Type.Variable()));
        }
      }
    }
    for (    Instruction inst : ((Program)node).instructions) {
      try {
        Type type=analyze(inst,env,nonGen);
      }
 catch (      TypeError e) {
        System.err.println("String_Node_Str" + env);
        throw new RuntimeException("String_Node_Str" + inst,e);
      }
    }
    return null;
  }
 else   if (node instanceof Expr.ENum) {
    return Type.INT;
  }
 else   if (node instanceof Expr.EBool) {
    return Type.BOOL;
  }
 else   if (node instanceof Expr.EStr) {
    return Type.STR;
  }
 else   if (node instanceof Expr.EChar) {
    return Type.CHAR;
  }
 else   if (node == Expr.EUnit) {
    return Type.UNIT;
  }
 else   if (node instanceof Expr.EList) {
    Type valueType=new Type.Variable();
    for (    Expr expr : ((Expr.EList)node).values) {
      unify(valueType,analyze(expr,env,nonGen));
    }
    return Type.List(valueType);
  }
 else   if (node instanceof Expr.ETuple) {
    List<Type> valuesTypes=new ArrayList<Type>();
    for (    Expr expr : ((Expr.ETuple)node).values) {
      valuesTypes.add(analyze(expr,env,nonGen));
    }
    return Type.Product(valuesTypes);
  }
 else   if (node instanceof Expr.ERecord) {
    Expr.ERecord rec=(Expr.ERecord)node;
    Map<String,Type> valuesTypes=new HashMap<String,Type>();
    for (    Map.Entry<String,Expr> entry : rec.values.entrySet()) {
      valuesTypes.put(entry.getKey(),analyze(entry.getValue(),env,nonGen));
    }
    return new Type.RecordType(valuesTypes);
  }
 else   if (node instanceof Expr.EName) {
    return getType(((Expr.EName)node).name,env,nonGen);
  }
 else   if (node instanceof Expr.EAccessor) {
    Expr.EAccessor acc=(Expr.EAccessor)node;
    Type objType=analyze(acc.obj,env,nonGen);
    Type.Variable res=new Type.Variable();
    Type.RecordType desiredType=new Type.RecordType(Collections.<String,Type>singletonMap(acc.field,res));
    unify(objType,desiredType);
    return res;
  }
 else   if (node instanceof Expr.EAp) {
    Expr.EAp ap=(Expr.EAp)node;
    Type funcType=analyze(ap.fn,env,nonGen);
    Type argType=analyze(ap.arg,env,nonGen);
    Type.Variable resType=new Type.Variable();
    try {
      unify(Type.Function(argType,resType),funcType);
    }
 catch (    TypeError e) {
      throw new TypeError("String_Node_Str" + ap,Type.Function(argType,resType),funcType,e);
    }
    return resType;
  }
 else   if (node instanceof Expr.EIf) {
    Expr.EIf eif=(Expr.EIf)node;
    Type condType=analyze(eif.cond,env,nonGen);
    if (!isException(condType)) {
      unify(condType,Type.BOOL);
    }
    Type thenType=null;
    for (    Instruction instr : eif.thenInstructions) {
      thenType=analyze(instr,env,nonGen);
    }
    Type elseType=null;
    for (    Instruction instr : eif.elseInstructions) {
      elseType=analyze(instr,env,nonGen);
    }
    if (!isException(thenType) && !isException(elseType)) {
      unify(thenType,elseType);
    }
    return isException(thenType) ? elseType : thenType;
  }
 else   if (node instanceof Expr.PatterMatching) {
    Expr.PatterMatching patmat=(Expr.PatterMatching)node;
    Type inputType=analyze(patmat.input,env,nonGen);
    Type resType=new Type.Variable();
    boolean allExceptions=true;
    for (    Expr.PatterMatching.Case pcase : patmat.cases) {
      TypeScope newScope=env.child();
      Type patType=visit(pcase.pattern,newScope,nonGen);
      if (!isException(inputType)) {
        unify(patType,inputType);
      }
      Type caseType=null;
      for (      Instruction instruction : pcase.outcome) {
        caseType=analyze(instruction,newScope,nonGen);
      }
      if (!isException(caseType)) {
        unify(caseType,resType);
        resType=caseType;
        allExceptions=false;
      }
    }
    return allExceptions ? Type.EXCEPTION : resType;
  }
 else   if (node instanceof Expr.EThrow) {
    Expr.EThrow ethrow=(Expr.EThrow)node;
    Type exType=analyze(ethrow.exception,env,nonGen);
    unify(exType,Type.EXCEPTION);
    return Type.EXCEPTION;
  }
 else   if (node instanceof Expr.TryCatch) {
    Expr.TryCatch tc=(Expr.TryCatch)node;
    Type tryType=null;
    for (    Instruction instr : tc.tryBody) {
      tryType=analyze(instr,env,nonGen);
    }
    tryType=prune(tryType);
    System.err.println("String_Node_Str" + tryType.getClass());
    System.err.println("String_Node_Str" + (tryType == Type.EXCEPTION));
    Type.Variable resType=new Type.Variable();
    if (!isException(tryType)) {
      System.err.println("String_Node_Str");
      unify(tryType,resType);
    }
    for (    Expr.PatterMatching.Case pcase : tc.catchCases) {
      TypeScope newScope=env.child();
      Type patType=visit(pcase.pattern,newScope,nonGen);
      unify(patType,Type.EXCEPTION);
      Type caseType=null;
      for (      Instruction instruction : pcase.outcome) {
        caseType=analyze(instruction,newScope,nonGen);
      }
      unify(caseType,resType);
    }
    return resType;
  }
 else   if (node instanceof Expr.ELam) {
    Expr.ELam lam=(Expr.ELam)node;
    TypeScope newEnv=env.child();
    Set<Type> newNonGen=new HashSet<Type>(nonGen);
    List<Type> argTypes=new ArrayList<Type>();
    for (    Named arg : lam.args) {
      Type argType=new Type.Variable();
      argTypes.add(argType);
      newEnv.define(arg.name,argType);
      newNonGen.add(argType);
    }
    Type resultType=null;
    for (    Instruction instr : lam.instructions) {
      resultType=analyze(instr,newEnv,newNonGen);
    }
    if (lam.type != null) {
      unify(resultType,lam.type);
    }
    return Type.Function(argTypes,resultType);
  }
 else   if (node instanceof LetBinding) {
    LetBinding let=(LetBinding)node;
    TypeScope newEnv=env.child();
    Set<Type> newNonGen=new HashSet<Type>(nonGen);
    List<Type> argTypes=new ArrayList<Type>();
    Type.Variable letTypeVar=new Type.Variable();
    newEnv.define(let.name,letTypeVar);
    newNonGen.add(letTypeVar);
    for (    Named arg : let.args) {
      Type argType=new Type.Variable();
      argTypes.add(argType);
      newEnv.define(arg.name,argType);
      newNonGen.add(argType);
    }
    Type resultType=null;
    for (    Instruction instr : let.instructions) {
      resultType=analyze(instr,newEnv,newNonGen);
    }
    if (let.type != null) {
      unify(resultType,let.type);
    }
    Type letType=Type.Function(argTypes,resultType);
    env.define(let.name,letType);
    return letType;
  }
 else   if (node instanceof DestructuringLetBinding) {
    DestructuringLetBinding let=(DestructuringLetBinding)node;
    TypeScope newEnv=env.child();
    Set<Type> newNonGen=new HashSet<Type>(nonGen);
    List<Type> argTypes=new ArrayList<Type>();
    Type letTypeVar=visit(let.main,newEnv,newNonGen);
    newNonGen.add(letTypeVar);
    for (    Pattern arg : let.args) {
      Type argType=visit(arg,newEnv,newNonGen);
      argTypes.add(argType);
    }
    Type resultType=null;
    for (    Instruction instr : let.instructions) {
      resultType=analyze(instr,newEnv,newNonGen);
    }
    Type letType=Type.Function(argTypes,resultType);
    define(let.main,letType,env);
    return letType;
  }
 else   if (node instanceof DataDecl) {
    DataDecl dataDecl=(DataDecl)node;
    for (    DataDecl.TypeConstructor tyCon : dataDecl.typeConstructors) {
      env.define(tyCon.name,Type.TyCon(tyCon,dataDecl));
    }
    return dataDecl.type;
  }
 else   if (node instanceof ExceptionDecl) {
    ExceptionDecl dataDecl=(ExceptionDecl)node;
    env.define(dataDecl.name,new Type.ExceptionCon(dataDecl.name,dataDecl.types));
    return Type.EXCEPTION;
  }
 else {
    throw new RuntimeException("String_Node_Str" + node.getClass());
  }
}