コード例 #1
0
 private Object reduceTypeEquality(TypeBinding object) {
   // 18.2.4
   if (this.left.kind() == Binding.WILDCARD_TYPE) {
     if (this.right.kind() == Binding.WILDCARD_TYPE) {
       // left and right are wildcards ("type arguments")
       WildcardBinding leftWC = (WildcardBinding) this.left;
       WildcardBinding rightWC = (WildcardBinding) this.right;
       if (leftWC.boundKind == Wildcard.UNBOUND && rightWC.boundKind == Wildcard.UNBOUND)
         return TRUE;
       if (leftWC.boundKind == Wildcard.UNBOUND && rightWC.boundKind == Wildcard.EXTENDS)
         return ConstraintTypeFormula.create(object, rightWC.bound, SAME, this.isSoft);
       if (leftWC.boundKind == Wildcard.EXTENDS && rightWC.boundKind == Wildcard.UNBOUND)
         return ConstraintTypeFormula.create(leftWC.bound, object, SAME, this.isSoft);
       if ((leftWC.boundKind == Wildcard.EXTENDS && rightWC.boundKind == Wildcard.EXTENDS)
           || (leftWC.boundKind == Wildcard.SUPER && rightWC.boundKind == Wildcard.SUPER)) {
         return ConstraintTypeFormula.create(leftWC.bound, rightWC.bound, SAME, this.isSoft);
       }
     }
   } else {
     if (this.right.kind() != Binding.WILDCARD_TYPE) {
       // left and right are types (vs. wildcards)
       if (this.left.isProperType(true) && this.right.isProperType(true)) {
         if (TypeBinding.equalsEquals(this.left, this.right)) return TRUE;
         return FALSE;
       }
       if (this.left instanceof InferenceVariable) {
         return new TypeBound((InferenceVariable) this.left, this.right, SAME, this.isSoft);
       }
       if (this.right instanceof InferenceVariable) {
         return new TypeBound((InferenceVariable) this.right, this.left, SAME, this.isSoft);
       }
       if ((this.left.isClass() || this.left.isInterface())
           && (this.right.isClass() || this.right.isInterface())
           && TypeBinding.equalsEquals(this.left.erasure(), this.right.erasure())) {
         TypeBinding[] leftParams = this.left.typeArguments();
         TypeBinding[] rightParams = this.right.typeArguments();
         if (leftParams == null || rightParams == null)
           return leftParams == rightParams ? TRUE : FALSE;
         if (leftParams.length != rightParams.length) return FALSE;
         int len = leftParams.length;
         ConstraintFormula[] constraints = new ConstraintFormula[len];
         for (int i = 0; i < len; i++) {
           constraints[i] =
               ConstraintTypeFormula.create(leftParams[i], rightParams[i], SAME, this.isSoft);
         }
         return constraints;
       }
       if (this.left.isArrayType()
           && this.right.isArrayType()
           && this.left.dimensions() == this.right.dimensions()) {
         // checking dimensions already now is an optimization over reducing one dim at a time
         return ConstraintTypeFormula.create(
             this.left.leafComponentType(), this.right.leafComponentType(), SAME, this.isSoft);
       }
     }
   }
   return FALSE;
 }
コード例 #2
0
 boolean addConstraintsFromTypeParameters(
     TypeBinding subCandidate, ParameterizedTypeBinding ca, List<ConstraintFormula> constraints) {
   TypeBinding[] ai = ca.arguments; // C<A1,A2,...>
   if (ai == null) return true; // no arguments here means nothing to check
   TypeBinding cb = subCandidate.findSuperTypeOriginatingFrom(ca); // C<B1,B2,...>
   if (cb == null) return false; // nothing here means we failed
   if (TypeBinding.equalsEquals(ca, cb)) // incl C#RAW vs C#RAW
   return true;
   if (!(cb instanceof ParameterizedTypeBinding)) {
     // if C is parameterized with its own type variables, there're no more constraints to be
     // created here, otherwise let's fail
     return ca.isParameterizedWithOwnVariables();
   }
   TypeBinding[] bi = ((ParameterizedTypeBinding) cb).arguments;
   if (cb.isRawType() || bi == null || bi.length == 0)
     return (this.isSoft && InferenceContext18.SIMULATE_BUG_JDK_8026527)
         ? true
         : false; // FALSE would conform to the spec
   for (int i = 0; i < ai.length; i++)
     constraints.add(
         ConstraintTypeFormula.create(bi[i], ai[i], TYPE_ARGUMENT_CONTAINED, this.isSoft));
   return true;
 }
コード例 #3
0
 // return: ReductionResult or ConstraintFormula[]
 public Object reduce(InferenceContext18 inferenceContext) {
   switch (this.relation) {
     case COMPATIBLE:
       // 18.2.2:
       if (this.left.isProperType(true) && this.right.isProperType(true)) {
         return this.left.isCompatibleWith(this.right, inferenceContext.scope)
                 || this.left.isBoxingCompatibleWith(this.right, inferenceContext.scope)
             ? TRUE
             : FALSE;
       }
       if (this.left.isPrimitiveType()) {
         TypeBinding sPrime = inferenceContext.environment.computeBoxingType(this.left);
         return ConstraintTypeFormula.create(sPrime, this.right, COMPATIBLE, this.isSoft);
       }
       if (this.right.isPrimitiveType()) {
         TypeBinding tPrime = inferenceContext.environment.computeBoxingType(this.right);
         return ConstraintTypeFormula.create(this.left, tPrime, SAME, this.isSoft);
       }
       switch (this.right.kind()) {
         case Binding.ARRAY_TYPE:
           if (this.right.leafComponentType().kind() != Binding.PARAMETERIZED_TYPE) break;
           // $FALL-THROUGH$ array of parameterized is handled below:
         case Binding.PARAMETERIZED_TYPE:
           {
             //															  this.right = G<T1,T2,...> or G<T1,T2,...>[]k
             TypeBinding gs =
                 this.left.findSuperTypeOriginatingFrom(
                     this.right); // G<S1,S2,...> or G<S1,S2,...>[]k
             if (gs != null && gs.leafComponentType().isRawType()) {
               inferenceContext.recordUncheckedConversion(this);
               return TRUE;
             }
             break;
           }
       }
       return ConstraintTypeFormula.create(this.left, this.right, SUBTYPE, this.isSoft);
     case SUBTYPE:
       // 18.2.3:
       return reduceSubType(inferenceContext.scope, this.left, this.right);
     case SUPERTYPE:
       // 18.2.3:
       return reduceSubType(inferenceContext.scope, this.right, this.left);
     case SAME:
       if (inferenceContext.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled)
         if (!checkIVFreeTVmatch(this.left, this.right)) checkIVFreeTVmatch(this.right, this.left);
       // 18.2.4:
       return reduceTypeEquality(inferenceContext.object);
     case TYPE_ARGUMENT_CONTAINED:
       // 18.2.3:
       if (this.right.kind()
           != Binding.WILDCARD_TYPE) { // "If T is a type" ... all alternatives require "wildcard"
         if (this.left.kind() != Binding.WILDCARD_TYPE) {
           return ConstraintTypeFormula.create(this.left, this.right, SAME, this.isSoft);
         } else {
           return FALSE;
         }
       } else {
         WildcardBinding t = (WildcardBinding) this.right;
         if (t.boundKind == Wildcard.UNBOUND) return TRUE;
         if (t.boundKind == Wildcard.EXTENDS) {
           if (this.left.kind() != Binding.WILDCARD_TYPE) {
             return ConstraintTypeFormula.create(this.left, t.bound, SUBTYPE, this.isSoft);
           } else {
             WildcardBinding s = (WildcardBinding) this.left;
             switch (s.boundKind) {
               case Wildcard.UNBOUND:
                 return ConstraintTypeFormula.create(
                     inferenceContext.object, t.bound, SUBTYPE, this.isSoft);
               case Wildcard.EXTENDS:
                 return ConstraintTypeFormula.create(s.bound, t.bound, SUBTYPE, this.isSoft);
               case Wildcard.SUPER:
                 return ConstraintTypeFormula.create(
                     inferenceContext.object, t.bound, SAME, this.isSoft);
               default:
                 throw new IllegalArgumentException(
                     "Unexpected boundKind " + s.boundKind); // $NON-NLS-1$
             }
           }
         } else { // SUPER
           if (this.left.kind() != Binding.WILDCARD_TYPE) {
             return ConstraintTypeFormula.create(t.bound, this.left, SUBTYPE, this.isSoft);
           } else {
             WildcardBinding s = (WildcardBinding) this.left;
             if (s.boundKind == Wildcard.SUPER) {
               return ConstraintTypeFormula.create(t.bound, s.bound, SUBTYPE, this.isSoft);
             } else {
               return FALSE;
             }
           }
         }
       }
     default:
       throw new IllegalStateException("Unexpected relation kind " + this.relation); // $NON-NLS-1$
   }
 }
コード例 #4
0
  private Object reduceSubType(Scope scope, TypeBinding subCandidate, TypeBinding superCandidate) {
    // 18.2.3 Subtyping Constraints
    if (subCandidate.isProperType(true) && superCandidate.isProperType(true)) {
      if (subCandidate.isCompatibleWith(superCandidate, scope)) return TRUE;
      return FALSE;
    }
    if (subCandidate.id == TypeIds.T_null) return TRUE;
    if (superCandidate.id == TypeIds.T_null) return FALSE;
    if (subCandidate instanceof InferenceVariable)
      return new TypeBound((InferenceVariable) subCandidate, superCandidate, SUBTYPE, this.isSoft);
    if (superCandidate instanceof InferenceVariable)
      return new TypeBound(
          (InferenceVariable) superCandidate,
          subCandidate,
          SUPERTYPE,
          this.isSoft); // normalize to have variable on LHS
    switch (superCandidate.kind()) {
      case Binding.GENERIC_TYPE:
      case Binding.TYPE:
      case Binding.RAW_TYPE:
        {
          if (subCandidate.isSubtypeOf(superCandidate)) return TRUE;
          return FALSE;
        }
      case Binding.PARAMETERIZED_TYPE:
        {
          List<ConstraintFormula> constraints = new ArrayList<>();
          while (superCandidate != null
              && superCandidate.kind() == Binding.PARAMETERIZED_TYPE
              && subCandidate != null) {
            if (!addConstraintsFromTypeParameters(
                subCandidate, (ParameterizedTypeBinding) superCandidate, constraints)) return FALSE;
            // travel to enclosing types to check if they have type parameters, too:
            superCandidate = superCandidate.enclosingType();
            subCandidate = subCandidate.enclosingType();
          }
          switch (constraints.size()) {
            case 0:
              return TRUE;
            case 1:
              return constraints.get(0);
            default:
              return constraints.toArray(new ConstraintFormula[constraints.size()]);
          }
        }
      case Binding.ARRAY_TYPE:
        TypeBinding tPrime = ((ArrayBinding) superCandidate).elementsType();
        // let S'[] be the most specific array type that is a supertype of S (or S itself)
        ArrayBinding sPrimeArray = null;
        switch (subCandidate.kind()) {
          case Binding.INTERSECTION_TYPE:
            {
              WildcardBinding intersection = (WildcardBinding) subCandidate;
              sPrimeArray =
                  findMostSpecificSuperArray(
                      intersection.bound, intersection.otherBounds, intersection);
              break;
            }
          case Binding.ARRAY_TYPE:
            sPrimeArray = (ArrayBinding) subCandidate;
            break;
          case Binding.TYPE_PARAMETER:
            {
              TypeVariableBinding subTVB = (TypeVariableBinding) subCandidate;
              sPrimeArray =
                  findMostSpecificSuperArray(subTVB.firstBound, subTVB.otherUpperBounds(), subTVB);
              break;
            }
          default:
            return FALSE;
        }
        if (sPrimeArray == null) return FALSE;
        TypeBinding sPrime = sPrimeArray.elementsType();
        if (!tPrime.isPrimitiveType() && !sPrime.isPrimitiveType()) {
          return ConstraintTypeFormula.create(sPrime, tPrime, SUBTYPE, this.isSoft);
        }
        return TypeBinding.equalsEquals(tPrime, sPrime) ? TRUE : FALSE; // same primitive type?

        // "type variable" has two implementations in JDT:
      case Binding.WILDCARD_TYPE:
        if (subCandidate.kind() == Binding.INTERSECTION_TYPE) {
          ReferenceBinding[] intersectingTypes = subCandidate.getIntersectingTypes();
          if (intersectingTypes != null)
            for (int i = 0; i < intersectingTypes.length; i++)
              if (TypeBinding.equalsEquals(intersectingTypes[i], superCandidate)) return true;
        }
        WildcardBinding variable = (WildcardBinding) superCandidate;
        if (variable.boundKind == Wildcard.SUPER)
          return ConstraintTypeFormula.create(subCandidate, variable.bound, SUBTYPE, this.isSoft);
        return FALSE;
      case Binding.TYPE_PARAMETER:
        // similar to wildcard, but different queries for lower bound
        if (subCandidate.kind() == Binding.INTERSECTION_TYPE) {
          ReferenceBinding[] intersectingTypes = subCandidate.getIntersectingTypes();
          if (intersectingTypes != null)
            for (int i = 0; i < intersectingTypes.length; i++)
              if (TypeBinding.equalsEquals(intersectingTypes[i], superCandidate)) return true;
        }
        if (superCandidate instanceof CaptureBinding) {
          CaptureBinding capture = (CaptureBinding) superCandidate;
          if (capture.lowerBound != null
              && (capture.firstBound == null || capture.firstBound.id == TypeIds.T_JavaLangObject))
            return ConstraintTypeFormula.create(
                subCandidate, capture.lowerBound, SUBTYPE, this.isSoft);
        }
        return FALSE;
      case Binding.INTERSECTION_TYPE:
        superCandidate = ((WildcardBinding) superCandidate).allBounds();
        // $FALL-THROUGH$
      case Binding.INTERSECTION_TYPE18:
        TypeBinding[] intersectingTypes =
            ((IntersectionTypeBinding18) superCandidate).intersectingTypes;
        ConstraintFormula[] result = new ConstraintFormula[intersectingTypes.length];
        for (int i = 0; i < intersectingTypes.length; i++) {
          result[i] =
              ConstraintTypeFormula.create(
                  subCandidate, intersectingTypes[i], SUBTYPE, this.isSoft);
        }
        return result;
      case Binding.POLY_TYPE:
        PolyTypeBinding poly = (PolyTypeBinding) superCandidate;
        Invocation invocation = (Invocation) poly.expression;
        MethodBinding binding = invocation.binding();
        if (binding == null || !binding.isValidBinding()) return FALSE;
        TypeBinding returnType =
            binding.isConstructor() ? binding.declaringClass : binding.returnType;
        return reduceSubType(
            scope,
            subCandidate,
            returnType.capture(scope, invocation.sourceStart(), invocation.sourceEnd()));
    }
    throw new IllegalStateException("Unexpected RHS " + superCandidate); // $NON-NLS-1$
  }