JSType meet(JSType that) {
    UnionTypeBuilder builder = new UnionTypeBuilder(registry);
    for (JSType alternate : alternatesWithoutStucturalTyping) {
      if (alternate.isSubtype(that)) {
        builder.addAlternate(alternate);
      }
    }

    if (that.isUnionType()) {
      for (JSType otherAlternate : that.toMaybeUnionType().alternatesWithoutStucturalTyping) {
        if (otherAlternate.isSubtype(this)) {
          builder.addAlternate(otherAlternate);
        }
      }
    } else if (that.isSubtype(this)) {
      builder.addAlternate(that);
    }
    JSType result = builder.build();
    if (!result.isNoType()) {
      return result;
    } else if (this.isObject() && (that.isObject() && !that.isNoType())) {
      return getNativeType(JSTypeNative.NO_OBJECT_TYPE);
    } else {
      return getNativeType(JSTypeNative.NO_TYPE);
    }
  }
  /**
   * Computes the greatest subtype of two related templatized types.
   *
   * @return The greatest subtype.
   */
  JSType getGreatestSubtypeHelper(JSType rawThat) {
    Preconditions.checkNotNull(rawThat);

    if (!wrapsSameRawType(rawThat)) {
      if (!rawThat.isTemplatizedType()) {
        if (this.isSubtype(rawThat)) {
          return this;
        } else if (rawThat.isSubtype(this)) {
          return filterNoResolvedType(rawThat);
        }
      }
      if (this.isObject() && rawThat.isObject()) {
        return this.getNativeType(JSTypeNative.NO_OBJECT_TYPE);
      }
      return this.getNativeType(JSTypeNative.NO_TYPE);
    }

    TemplatizedType that = rawThat.toMaybeTemplatizedType();
    Preconditions.checkNotNull(that);

    if (getTemplateTypeMap()
        .checkEquivalenceHelper(
            that.getTemplateTypeMap(), EquivalenceMethod.INVARIANT, SubtypingMode.NORMAL)) {
      return this;
    }

    // For types that have the same raw type but different type parameters,
    // we simply create a type has a "unknown" type parameter.  This is
    // equivalent to the raw type.
    return getReferencedObjTypeInternal();
  }
Esempio n. 3
0
 @Override
 public boolean isSubtype(JSType that) {
   if (JSType.isSubtype(this, that)) {
     return true;
   } else {
     return that.isObject() && !that.isNoType() && !that.isNoResolvedType();
   }
 }
 /**
  * Returns a more restricted union type than {@code this} one, in which all subtypes of {@code
  * type} have been removed.
  *
  * <p>Examples:
  *
  * <ul>
  *   <li>{@code (number,string)} restricted by {@code number} is {@code string}
  *   <li>{@code (null, EvalError, URIError)} restricted by {@code Error} is {@code null}
  * </ul>
  *
  * @param type the supertype of the types to remove from this union type
  */
 public JSType getRestrictedUnion(JSType type) {
   UnionTypeBuilder restricted = new UnionTypeBuilder(registry);
   for (JSType t : alternatesWithoutStucturalTyping) {
     // Keep all unknown/unresolved types.
     if (t.isUnknownType() || t.isNoResolvedType() || !t.isSubtype(type)) {
       restricted.addAlternate(t);
     }
   }
   return restricted.build();
 }
 @Override
 public TernaryValue testForEquality(JSType that) {
   TernaryValue result = super.testForEquality(that);
   if (result != null) {
     return result;
   }
   if (that.isUnknownType()
       || that.isSubtype(getNativeType(JSTypeNative.OBJECT_NUMBER_STRING_BOOLEAN))) {
     return UNKNOWN;
   }
   return FALSE;
 }
  @Override
  public JSType getLeastSupertype(JSType that) {
    if (!that.isUnknownType() && !that.isUnionType()) {
      for (JSType alternate : alternatesWithoutStucturalTyping) {
        if (!alternate.isUnknownType() && that.isSubtype(alternate)) {
          return this;
        }
      }
    }

    return getLeastSupertype(this, that);
  }
 private boolean isSubtype(JSType rightType, JSType leftType, boolean isStructural) {
   // if thisType or thatType is an unresolved templatized type,
   // then there is no structural interface matching
   boolean thisUnresolved =
       rightType.isTemplatizedType() && !rightType.toMaybeTemplatizedType().isResolved();
   boolean thatUnresolved =
       leftType.isTemplatizedType() && !leftType.toMaybeTemplatizedType().isResolved();
   if (isStructural && !thisUnresolved && !thatUnresolved) {
     return rightType.isSubtype(leftType);
   } else {
     return rightType.isSubtypeWithoutStructuralTyping(leftType);
   }
 }
 @Override
 protected boolean isSubtype(JSType that, ImplCache implicitImplCache) {
   // unknown
   if (that.isUnknownType()) {
     return true;
   }
   // all type
   if (that.isAllType()) {
     return true;
   }
   for (JSType element : alternatesWithoutStucturalTyping) {
     if (!element.isSubtype(that, implicitImplCache)) {
       return false;
     }
   }
   return true;
 }
Esempio n. 9
0
  /** Determines if typeA is a subtype of typeB */
  static boolean isSubtype(ObjectType typeA, RecordType typeB) {
    // typeA is a subtype of record type typeB iff:
    // 1) typeA has all the properties declared in typeB.
    // 2) And for each property of typeB,
    //    2a) if the property of typeA is declared, it must be equal
    //        to the type of the property of typeB,
    //    2b) otherwise, it must be a subtype of the property of typeB.
    //
    // To figure out why this is true, consider the following pseudo-code:
    // /** @type {{a: (Object,null)}} */ var x;
    // /** @type {{a: !Object}} */ var y;
    // var z = {a: {}};
    // x.a = null;
    //
    // y cannot be assigned to x, because line 4 would violate y's declared
    // properties. But z can be assigned to x. Even though z and y are the
    // same type, the properties of z are inferred--and so an assignment
    // to the property of z would not violate any restrictions on it.
    for (String property : typeB.getOwnPropertyNames()) {
      if (!typeA.hasProperty(property)) {
        return false;
      }

      JSType propA = typeA.getPropertyType(property);
      JSType propB = typeB.getPropertyType(property);
      if (typeA.isPropertyTypeDeclared(property)) {
        // If one declared property isn't invariant,
        // then the whole record isn't covariant.
        if (!propA.isInvariant(propB)) {
          return false;
        }
      } else {
        // If one inferred property isn't a subtype,
        // then the whole record isn't covariant.
        if (!propA.isSubtype(propB)) {
          return false;
        }
      }
    }

    return true;
  }