Program: 27140
Project: 27140
Buggy source:
/** 
 * Updates the scope according to the result of a type change, like an assignment or a type cast.
 */
private void updateScopeForTypeChange(FlowScope scope,Node left,JSType leftType,JSType resultType){
  checkNotNull(resultType);
  Node right=NodeUtil.getRValueOfLValue(left);
  if (isPossibleMixinApplication(left,right)) {
    addMissingInterfaceProperties(leftType);
  }
switch (left.getToken()) {
case NAME:
    String varName=left.getString();
  TypedVar var=syntacticScope.getVar(varName);
JSType varType=var == null ? null : var.getType();
boolean isVarDeclaration=left.hasChildren() && varType != null && !var.isTypeInferred();
boolean isTypelessConstDecl=isVarDeclaration && NodeUtil.isConstantDeclaration(compiler.getCodingConvention(),var.getJSDocInfo(),var.getNameNode()) && !(var.getJSDocInfo() != null && var.getJSDocInfo().hasType());
boolean isVarTypeBetter=isVarDeclaration && !resultType.isNullType() && !resultType.isVoidType()&& !isTypelessConstDecl;
if (isVarTypeBetter) {
redeclareSimpleVar(scope,left,varType);
}
 else {
redeclareSimpleVar(scope,left,resultType);
}
left.setJSType(resultType);
if (var != null && var.isTypeInferred()) {
JSType oldType=var.getType();
var.setType(oldType == null ? resultType : oldType.getLeastSupertype(resultType));
}
 else if (isTypelessConstDecl) {
var.setType(resultType);
}
break;
case GETPROP:
if (left.isQualifiedName()) {
String qualifiedName=left.getQualifiedName();
boolean declaredSlotType=false;
JSType rawObjType=left.getFirstChild().getJSType();
if (rawObjType != null) {
ObjectType objType=ObjectType.cast(rawObjType.restrictByNotNullOrUndefined());
if (objType != null) {
String propName=left.getLastChild().getString();
declaredSlotType=objType.isPropertyTypeDeclared(propName);
}
}
JSType safeLeftType=leftType == null ? unknownType : leftType;
scope.inferQualifiedSlot(left,qualifiedName,safeLeftType,resultType,declaredSlotType);
}
left.setJSType(resultType);
ensurePropertyDefined(left,resultType);
break;
default :
break;
}
}

Fixed version (ground truth):
/** 
 * Updates the scope according to the result of a type change, like an assignment or a type cast.
 */
private void updateScopeForTypeChange(FlowScope scope,Node left,JSType leftType,JSType resultType){
  checkNotNull(resultType);
  Node right=NodeUtil.getRValueOfLValue(left);
  if (isPossibleMixinApplication(left,right)) {
    addMissingInterfaceProperties(leftType);
  }
  if (isLooseAssignmentToPrototype(left,leftType,resultType)) {
    return;
  }
switch (left.getToken()) {
case NAME:
    String varName=left.getString();
  TypedVar var=syntacticScope.getVar(varName);
JSType varType=var == null ? null : var.getType();
boolean isVarDeclaration=left.hasChildren() && varType != null && !var.isTypeInferred();
boolean isTypelessConstDecl=isVarDeclaration && NodeUtil.isConstantDeclaration(compiler.getCodingConvention(),var.getJSDocInfo(),var.getNameNode()) && !(var.getJSDocInfo() != null && var.getJSDocInfo().hasType());
boolean isVarTypeBetter=isVarDeclaration && !resultType.isNullType() && !resultType.isVoidType()&& !isTypelessConstDecl;
if (isVarTypeBetter) {
redeclareSimpleVar(scope,left,varType);
}
 else {
redeclareSimpleVar(scope,left,resultType);
}
left.setJSType(resultType);
if (var != null && var.isTypeInferred()) {
JSType oldType=var.getType();
var.setType(oldType == null ? resultType : oldType.getLeastSupertype(resultType));
}
 else if (isTypelessConstDecl) {
var.setType(resultType);
}
break;
case GETPROP:
if (left.isQualifiedName()) {
String qualifiedName=left.getQualifiedName();
boolean declaredSlotType=false;
JSType rawObjType=left.getFirstChild().getJSType();
if (rawObjType != null) {
ObjectType objType=ObjectType.cast(rawObjType.restrictByNotNullOrUndefined());
if (objType != null) {
String propName=left.getLastChild().getString();
declaredSlotType=objType.isPropertyTypeDeclared(propName);
}
}
JSType safeLeftType=leftType == null ? unknownType : leftType;
scope.inferQualifiedSlot(left,qualifiedName,safeLeftType,resultType,declaredSlotType);
}
left.setJSType(resultType);
ensurePropertyDefined(left,resultType);
break;
default :
break;
}
}