Program: 27184
Project: 27184
Buggy source:
/** 
 * For each qualified name N in the global scope, we check if: (a) No ancestor of N is ever aliased or assigned an unknown value type. (If N = "a.b.c", "a" and "a.b" are never aliased). (b) N has exactly one write, and it lives in the global scope. (c) N is aliased in a local scope. (d) N is aliased in global scope <p>If (a) is true, then GlobalNamespace must know all the writes to N. If (a) and (b) are true, then N cannot change during the execution of a local scope. If (a) and (b) and (c) are true, then the alias can be inlined if the alias obeys the usual rules for how we decide whether a variable is inlineable. If (a) and (b) and (d) are true, then inline the alias if possible (if it is assigned exactly once unconditionally). <p>For (a), (b), and (c) are true and the alias is of a constructor, we may also partially inline the alias - i.e. replace some references with the constructor but not all - since constructor properties are always collapsed, so we want to be more aggressive about removing aliases.
 * @see InlineVariables
 */
private void inlineAliases(GlobalNamespace namespace){
  Deque<Name> workList=new ArrayDeque<>(namespace.getNameForest());
  while (!workList.isEmpty()) {
    Name name=workList.pop();
    if (name.type == Name.Type.GET || name.type == Name.Type.SET) {
      continue;
    }
    if (!name.inExterns && name.globalSets == 1 && name.localSets == 0 && name.aliasingGets > 0) {
      List<Ref> refs=new ArrayList<>(name.getRefs());
      for (      Ref ref : refs) {
        Scope hoistScope=ref.scope.getClosestHoistScope();
        if (ref.type == Type.ALIASING_GET && !mayBeGlobalAlias(ref)) {
          if (inlineAliasIfPossible(name,ref,namespace)) {
            name.removeRef(ref);
          }
        }
 else         if (ref.type == Type.ALIASING_GET && hoistScope.isGlobal() && ref.getTwin() == null) {
          if (inlineGlobalAliasIfPossible(name,ref,namespace)) {
            name.removeRef(ref);
          }
        }
      }
    }
    if (!name.inExterns && name.type == Name.Type.CLASS) {
      List<Name> subclasses=name.subclasses;
      if (subclasses != null && name.props != null) {
        for (        Name subclass : subclasses) {
          for (          Name prop : name.props) {
            rewriteAllSubclassInheritedAccesses(name,subclass,prop,namespace);
          }
        }
      }
    }
    if ((name.type == Name.Type.OBJECTLIT || name.type == Name.Type.FUNCTION || name.type == Name.Type.CLASS) && name.aliasingGets == 0 && name.props != null) {
      workList.addAll(name.props);
    }
  }
}

Fixed version (ground truth):
/** 
 * For each qualified name N in the global scope, we check if: (a) No ancestor of N is ever aliased or assigned an unknown value type. (If N = "a.b.c", "a" and "a.b" are never aliased). (b) N has exactly one write, and it lives in the global scope. (c) N is aliased in a local scope. (d) N is aliased in global scope <p>If (a) is true, then GlobalNamespace must know all the writes to N. If (a) and (b) are true, then N cannot change during the execution of a local scope. If (a) and (b) and (c) are true, then the alias can be inlined if the alias obeys the usual rules for how we decide whether a variable is inlineable. If (a) and (b) and (d) are true, then inline the alias if possible (if it is assigned exactly once unconditionally). <p>For (a), (b), and (c) are true and the alias is of a constructor, we may also partially inline the alias - i.e. replace some references with the constructor but not all - since constructor properties are always collapsed, so we want to be more aggressive about removing aliases.
 * @see InlineVariables
 */
private void inlineAliases(GlobalNamespace namespace){
  Deque<Name> workList=new ArrayDeque<>(namespace.getNameForest());
  while (!workList.isEmpty()) {
    Name name=workList.pop();
    if (name.type == Name.Type.GET || name.type == Name.Type.SET) {
      continue;
    }
    if (!name.inExterns && name.globalSets == 1 && name.localSets == 0 && name.aliasingGets > 0) {
      List<Ref> refs=new ArrayList<>(name.getRefs());
      for (      Ref ref : refs) {
        Scope hoistScope=ref.scope.getClosestHoistScope();
        if (ref.type == Type.ALIASING_GET && !mayBeGlobalAlias(ref)) {
          if (inlineAliasIfPossible(name,ref,namespace)) {
            name.removeRef(ref);
          }
        }
 else         if (ref.type == Type.ALIASING_GET && hoistScope.isGlobal() && ref.getTwin() == null) {
          if (inlineGlobalAliasIfPossible(name,ref,namespace)) {
            name.removeRef(ref);
          }
        }
      }
    }
    if (!name.inExterns && name.type == Name.Type.CLASS) {
      List<Name> subclasses=name.subclasses;
      if (subclasses != null && name.props != null) {
        for (        Name subclass : subclasses) {
          for (          Name prop : name.props) {
            rewriteAllSubclassInheritedAccesses(name,subclass,prop,namespace);
          }
        }
      }
    }
    if ((name.type == Name.Type.OBJECTLIT || name.type == Name.Type.FUNCTION) && name.aliasingGets == 0 && name.props != null) {
      workList.addAll(name.props);
    }
  }
}