Exemple #1
0
  /**
   * Return the greatest lower bound of two types. That is, return the largest type that is a
   * subtype of both inputs. If none exists return {@code thisType}.
   */
  public JReferenceType strengthenType(JReferenceType thisType, JReferenceType thatType) {
    if (thisType == thatType) {
      return thisType;
    }

    if (thisType.isNullType() || thatType.isNullType()) {
      return JReferenceType.NULL_TYPE;
    }

    if (thisType.canBeNull() != thatType.canBeNull()) {
      // If either is non-nullable, the result should be non-nullable.
      return strengthenType(thisType.strengthenToNonNull(), thatType.strengthenToNonNull());
    }

    if (typeOracle.castSucceedsTrivially(thisType, thatType)) {
      return thisType;
    }

    if (typeOracle.castSucceedsTrivially(thatType, thisType)) {
      return thatType;
    }

    // This types are incompatible; ideally this code should not be reached, but there are two
    // situations where this happens:
    //   1 - unrelated interfaces;
    //   2 - unsafe code.
    // The original type is preserved in this case.
    return thisType;
  }
Exemple #2
0
  private JReferenceType generalizeArrayTypes(JArrayType thisArrayType, JArrayType thatArrayType) {
    assert thisArrayType != thatArrayType;

    int thisDims = thisArrayType.getDims();
    int thatDims = thatArrayType.getDims();

    int minDims = Math.min(thisDims, thatDims);
    /*
     * At a bare minimum, any two arrays generalize to an Object array with
     * one less dim than the lesser of the two; that is, int[][][][] and
     * String[][][] generalize to Object[][]. If minDims is 1, then they
     * just generalize to Object.
     */
    JReferenceType minimalGeneralType =
        (minDims == 1) ? typeJavaLangObject : getOrCreateArrayType(typeJavaLangObject, minDims - 1);

    if (thisDims == thatDims) {

      // Try to generalize by leaf types
      JType thisLeafType = thisArrayType.getLeafType();
      JType thatLeafType = thatArrayType.getLeafType();

      if (!(thisLeafType instanceof JReferenceType) || !(thatLeafType instanceof JReferenceType)) {
        return minimalGeneralType;
      }

      /*
       * Both are reference types; the result is the generalization of the leaf types combined with
       * the number of dims; that is, Foo[] and Bar[] generalize to X[] where X is the
       * generalization of Foo and Bar.
       *
       * Never generalize arrays to arrays of {@link JAnalysisDecoratedType}. One of the reasons is
       * that array initialization is not accounted for in {@link TypeTightener}.
       */
      JReferenceType leafGeneralization =
          generalizeTypes((JReferenceType) thisLeafType, (JReferenceType) thatLeafType)
              .getUnderlyingType();
      return getOrCreateArrayType(leafGeneralization, thisDims);
    }

    // Different number of dims
    if (typeOracle.castSucceedsTrivially(thatArrayType, thisArrayType)) {
      return thisArrayType;
    }

    if (typeOracle.castSucceedsTrivially(thisArrayType, thatArrayType)) {
      return thatArrayType;
    }

    // Totally unrelated
    return minimalGeneralType;
  }
Exemple #3
0
  private JReferenceType generalizeInterfaces(
      JInterfaceType thisInterface, JInterfaceType thatInterface) {
    if (typeOracle.castSucceedsTrivially(thisInterface, thatInterface)) {
      return thatInterface;
    }

    if (typeOracle.castSucceedsTrivially(thatInterface, thisInterface)) {
      return thisInterface;
    }

    // unrelated
    return typeJavaLangObject;
  }
Exemple #4
0
  private JReferenceType generalizeUnderlyingTypes(
      JReferenceType thisType, JReferenceType thatType) {

    // We should not have any analysis properties from this point forward.
    assert thisType == thisType.getUnderlyingType() && thatType == thatType.getUnderlyingType();

    if (thisType == thatType) {
      return thisType;
    }

    if (thisType instanceof JInterfaceType && thatType instanceof JInterfaceType) {
      return generalizeInterfaces((JInterfaceType) thisType, (JInterfaceType) thatType);
    }

    if (thisType instanceof JArrayType && thatType instanceof JArrayType) {
      return generalizeArrayTypes((JArrayType) thisType, (JArrayType) thatType);
    }

    if (thisType instanceof JClassType && thatType instanceof JClassType) {
      return generalizeClasses((JClassType) thisType, (JClassType) thatType);
    }

    JInterfaceType interfaceType =
        thisType instanceof JInterfaceType
            ? (JInterfaceType) thisType
            : (thatType instanceof JInterfaceType ? (JInterfaceType) thatType : null);

    JReferenceType nonInterfaceType = interfaceType == thisType ? thatType : thisType;

    // See if the class or the array is castable to the interface type.
    if (interfaceType != null
        && typeOracle.castSucceedsTrivially(nonInterfaceType, interfaceType)) {
      return interfaceType;
    }

    // unrelated: the best commonality is Object
    return typeJavaLangObject;
  }