Beispiel #1
0
  /**
   * Unify the two types symmetrically, given that we have already instantiated the type variables
   * of interest in {@code t1} and {@code t2}, treating JSType.UNKNOWN as a "hole" to be filled.
   *
   * @return The unified type, or null if unification fails
   */
  static JSType unifyUnknowns(JSType t1, JSType t2) {
    if (t1.isUnknown()) {
      return t2;
    } else if (t2.isUnknown()) {
      return t1;
    } else if (t1.isTop() && t2.isTop()) {
      return TOP;
    } else if (t1.isTop() || t2.isTop()) {
      return null;
    }

    int t1Mask = promoteBoolean(t1.mask);
    int t2Mask = promoteBoolean(t2.mask);
    if (t1Mask != t2Mask || !Objects.equal(t1.typeVar, t2.typeVar)) {
      return null;
    }
    // All scalar types are equal
    if ((t1Mask & NON_SCALAR_MASK) == 0) {
      return t1;
    }
    if (t1.objs.size() != t2.objs.size()) {
      return null;
    }

    Set<ObjectType> ununified = Sets.newHashSet(t2.objs);
    Set<ObjectType> unifiedObjs = Sets.newHashSet();
    for (ObjectType objType1 : t1.objs) {
      ObjectType unified = objType1;
      boolean hasUnified = false;
      for (ObjectType objType2 : t2.objs) {
        ObjectType tmp = ObjectType.unifyUnknowns(unified, objType2);
        if (tmp != null) {
          hasUnified = true;
          ununified.remove(objType2);
          unified = tmp;
        }
      }
      if (!hasUnified) {
        return null;
      }
      unifiedObjs.add(unified);
    }
    if (!ununified.isEmpty()) {
      return null;
    }
    return new JSType(t1Mask, null, ImmutableSet.copyOf(unifiedObjs), t1.typeVar);
  }