예제 #1
0
 void addTypeToUnion(
     ProducedType ct, Map<TypeParameter, ProducedType> substitutions, List<ProducedType> types) {
   if (ct == null) {
     types.add(null);
   } else {
     addToUnion(types, substitute(ct, substitutions));
   }
 }
예제 #2
0
 /**
  * Eliminate the given type from the union type. (Performs a set complement operation.) Note that
  * this operation is not robust and only works if this is a union of the given type with some
  * other types that don't involve the given type.
  */
 public ProducedType minus(ClassOrInterface ci) {
   if (getDeclaration().equals(ci)) {
     return new BottomType(getDeclaration().getUnit()).getType();
   } else if (getDeclaration() instanceof UnionType) {
     List<ProducedType> types = new ArrayList<ProducedType>();
     for (ProducedType ct : getCaseTypes()) {
       if (ct.getSupertype(ci) == null) {
         addToUnion(types, ct.minus(ci));
       }
     }
     UnionType ut = new UnionType(getDeclaration().getUnit());
     ut.setCaseTypes(types);
     return ut.getType();
   } else {
     return this;
   }
 }
예제 #3
0
 private ProducedType getCommonSupertype(
     final List<ProducedType> caseTypes,
     TypeDeclaration dec,
     final TypeDeclaration selfTypeToIgnore) {
   // now try to construct a common produced
   // type that is a common supertype by taking
   // the type args and unioning them
   List<ProducedType> args = new ArrayList<ProducedType>();
   for (TypeParameter tp : dec.getTypeParameters()) {
     List<ProducedType> list2 = new ArrayList<ProducedType>();
     ProducedType result;
     if (tp.isContravariant()) {
       for (ProducedType pt : caseTypes) {
         ProducedType st = pt.getSupertype(dec, selfTypeToIgnore);
         if (st == null) {
           return null;
         }
         addToIntersection(list2, st.getTypeArguments().get(tp));
       }
       IntersectionType it = new IntersectionType(getDeclaration().getUnit());
       it.setSatisfiedTypes(list2);
       result = it.canonicalize().getType();
     } else {
       for (ProducedType pt : caseTypes) {
         ProducedType st = pt.getSupertype(dec, selfTypeToIgnore);
         if (st == null) {
           return null;
         }
         addToUnion(list2, st.getTypeArguments().get(tp));
       }
       UnionType ut = new UnionType(getDeclaration().getUnit());
       ut.setCaseTypes(list2);
       result = ut.getType();
     }
     args.add(result);
   }
   // check that the unioned type args
   // satisfy the type constraints
   for (int i = 0; i < args.size(); i++) {
     TypeParameter tp = dec.getTypeParameters().get(i);
     for (ProducedType ub : tp.getSatisfiedTypes()) {
       if (!args.get(i).isSubtypeOf(ub)) {
         return null;
       }
     }
   }
   // recurse to the qualifying type
   ProducedType outerType;
   if (dec.isMember()) {
     TypeDeclaration outer = (TypeDeclaration) dec.getContainer();
     List<ProducedType> list = new ArrayList<ProducedType>();
     for (ProducedType pt : caseTypes) {
       ProducedType st = pt.getQualifyingType().getSupertype(outer, null);
       list.add(st);
     }
     outerType = getCommonSupertype(list, outer, null);
   } else {
     outerType = null;
   }
   // make the resulting type
   ProducedType candidateResult = dec.getProducedType(outerType, args);
   // check the the resulting type is *really*
   // a subtype (take variance into account)
   for (ProducedType pt : caseTypes) {
     if (!pt.isSubtypeOf(candidateResult)) {
       return null;
     }
   }
   return candidateResult;
 }