private ArrayBinding findMostSpecificSuperArray(
     TypeBinding firstBound, TypeBinding[] otherUpperBounds, TypeBinding theType) {
   int numArrayBounds = 0;
   ArrayBinding result = null;
   if (firstBound != null && firstBound.isArrayType()) {
     result = (ArrayBinding) firstBound;
     numArrayBounds++;
   }
   for (int i = 0; i < otherUpperBounds.length; i++) {
     if (otherUpperBounds[i].isArrayType()) {
       result = (ArrayBinding) otherUpperBounds[i];
       numArrayBounds++;
     }
   }
   if (numArrayBounds == 0) return null;
   if (numArrayBounds == 1) return result;
   InferenceContext18.missingImplementation(
       "Extracting array from intersection is not defined"); //$NON-NLS-1$
   return null;
 }
 // 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$
   }
 }