use of org.checkerframework.framework.util.AnnotationMirrorSet in project checker-framework by typetools.
the class SupertypesSolver method targetToTypeLubs.
/**
* For each target, lub all of the types/annotations in its supertypes constraints and return
* the lubs
*
* @param remainingTargets targets that do not already have an inferred type argument
* @param constraintMap the set of constraints for all targets
* @return the lub determined for each target that has at least 1 supertype constraint
*/
private Lubs targetToTypeLubs(Set<TypeVariable> remainingTargets, ConstraintMap constraintMap, AnnotatedTypeFactory typeFactory) {
final QualifierHierarchy qualifierHierarchy = typeFactory.getQualifierHierarchy();
final AnnotationMirrorSet tops = new AnnotationMirrorSet(qualifierHierarchy.getTopAnnotations());
Lubs solution = new Lubs();
AnnotationMirrorMap<AnnotationMirror> lubOfPrimaries = new AnnotationMirrorMap<>();
List<TypeVariable> targetsSupertypesLast = new ArrayList<>(remainingTargets);
final Types types = typeFactory.getProcessingEnv().getTypeUtils();
// If we have two type variables <A, A extends B> order them B then A
// this is required because we will use the fact that A must be above B
// when determining the LUB of A
Collections.sort(targetsSupertypesLast, new Comparator<TypeVariable>() {
@Override
public int compare(TypeVariable o1, TypeVariable o2) {
if (types.isSubtype(o1, o2)) {
return -1;
} else if (types.isSubtype(o2, o1)) {
return 1;
}
return 0;
}
});
for (final TypeVariable target : targetsSupertypesLast) {
TargetConstraints targetRecord = constraintMap.getConstraints(target);
final AnnotationMirrorMap<AnnotationMirrorSet> subtypeAnnos = targetRecord.supertypes.primaries;
final Map<AnnotatedTypeMirror, AnnotationMirrorSet> subtypesOfTarget = targetRecord.supertypes.types;
// If this target is a supertype of other targets and those targets have already been
// lubbed add that LUB to the list of lubs for this target (as it must be above this
// target).
propagatePreviousLubs(targetRecord, solution, subtypesOfTarget);
// lub all the primary annotations and put them in lubOfPrimaries
lubPrimaries(lubOfPrimaries, subtypeAnnos, tops, qualifierHierarchy);
solution.addPrimaries(target, lubOfPrimaries);
if (subtypesOfTarget.keySet().size() > 0) {
final AnnotatedTypeMirror lub = leastUpperBound(target, typeFactory, subtypesOfTarget);
final AnnotationMirrorSet effectiveLubAnnos = new AnnotationMirrorSet(lub.getEffectiveAnnotations());
for (AnnotationMirror lubAnno : effectiveLubAnnos) {
final AnnotationMirror hierarchy = qualifierHierarchy.getTopAnnotation(lubAnno);
final AnnotationMirror primaryLub = lubOfPrimaries.get(hierarchy);
if (primaryLub != null) {
if (qualifierHierarchy.isSubtype(lubAnno, primaryLub) && !AnnotationUtils.areSame(lubAnno, primaryLub)) {
lub.replaceAnnotation(primaryLub);
}
}
}
solution.addType(target, lub);
}
}
return solution;
}
use of org.checkerframework.framework.util.AnnotationMirrorSet in project checker-framework by typetools.
the class SupertypesSolver method mergeLubTypeWithEqualities.
/**
* We previously found a type that is equal to target but not in all hierarchies. Use the
* primary annotations from the lub type to fill in the missing annotations in this type. Use
* that type as the inferred argument.
*
* <p>If we failed to infer any annotation for a given hierarchy, either previously from
* equalities or from the lub, return null.
*/
protected InferredType mergeLubTypeWithEqualities(final TypeVariable target, final AnnotatedTypeMirror lub, final ConstraintMap constraintMap, final AnnotatedTypeFactory typeFactory) {
final Equalities equalities = constraintMap.getConstraints(target).equalities;
final AnnotationMirrorSet tops = new AnnotationMirrorSet(typeFactory.getQualifierHierarchy().getTopAnnotations());
if (!equalities.types.isEmpty()) {
// there should be only one equality type if any at this point
final Entry<AnnotatedTypeMirror, AnnotationMirrorSet> eqEntry = equalities.types.entrySet().iterator().next();
final AnnotatedTypeMirror equalityType = eqEntry.getKey();
final AnnotationMirrorSet equalityAnnos = eqEntry.getValue();
boolean failed = false;
for (final AnnotationMirror top : tops) {
if (!equalityAnnos.contains(top)) {
final AnnotationMirror lubAnno = lub.getAnnotationInHierarchy(top);
if (lubAnno == null) {
// unannotated then "NO ANNOTATION" is the correct choice.
if (lub.getKind() == TypeKind.TYPEVAR && equalityType.getUnderlyingType().equals(lub.getUnderlyingType())) {
equalityAnnos.add(top);
} else {
failed = true;
}
} else {
equalityType.replaceAnnotation(lubAnno);
equalityAnnos.add(top);
}
}
}
if (!failed) {
return new InferredType(equalityType);
}
}
return new InferredType(lub);
}
use of org.checkerframework.framework.util.AnnotationMirrorSet in project checker-framework by typetools.
the class SupertypesSolver method mergeLubAnnosWithEqualities.
/**
* We previously found a type that is equal to target but not in all hierarchies. Use the
* primary annotations from the lub annos to fill in the missing annotations in this type. Use
* that type as the inferred argument.
*
* <p>If we failed to infer any annotation for a given hierarchy, either previously from
* equalities or from the lub, return null.
*/
protected InferredType mergeLubAnnosWithEqualities(final TypeVariable target, final AnnotationMirrorMap<AnnotationMirror> lubAnnos, final ConstraintMap constraintMap, final AnnotatedTypeFactory typeFactory) {
final Equalities equalities = constraintMap.getConstraints(target).equalities;
final AnnotationMirrorSet tops = new AnnotationMirrorSet(typeFactory.getQualifierHierarchy().getTopAnnotations());
if (!equalities.types.isEmpty()) {
// there should be only equality type if any at this point
final Entry<AnnotatedTypeMirror, AnnotationMirrorSet> eqEntry = equalities.types.entrySet().iterator().next();
final AnnotatedTypeMirror equalityType = eqEntry.getKey();
final AnnotationMirrorSet equalityAnnos = eqEntry.getValue();
boolean failed = false;
for (final AnnotationMirror top : tops) {
if (!equalityAnnos.contains(top)) {
final AnnotationMirror lubAnno = lubAnnos.get(top);
if (lubAnno == null) {
failed = true;
} else {
equalityType.replaceAnnotation(lubAnno);
equalityAnnos.add(top);
}
}
}
if (!failed) {
return new InferredType(equalityType);
}
}
return null;
}
use of org.checkerframework.framework.util.AnnotationMirrorSet in project checker-framework by typetools.
the class SupertypesSolver method leastUpperBound.
/**
* Successively calls least upper bound on the elements of types. Unlike
* AnnotatedTypes.leastUpperBound, this method will box primitives if necessary
*/
public static AnnotatedTypeMirror leastUpperBound(final TypeVariable target, final AnnotatedTypeFactory typeFactory, final Map<AnnotatedTypeMirror, AnnotationMirrorSet> types) {
QualifierHierarchy qualifierHierarchy = typeFactory.getQualifierHierarchy();
AnnotatedTypeVariable targetsDeclaredType = (AnnotatedTypeVariable) typeFactory.getAnnotatedType(target.asElement());
final AnnotationMirrorMap<AnnotationMirror> lowerBoundAnnos = TypeArgInferenceUtil.createHierarchyMap(new AnnotationMirrorSet(targetsDeclaredType.getLowerBound().getEffectiveAnnotations()), qualifierHierarchy);
final Iterator<Entry<AnnotatedTypeMirror, AnnotationMirrorSet>> typesIter = types.entrySet().iterator();
if (!typesIter.hasNext()) {
ErrorReporter.errorAbort("Calling LUB on empty list!");
}
/**
* If a constraint implies that a type parameter Ti is a supertype of an annotated type
* mirror Ai but only in a subset of all qualifier hierarchies then for all other qualifier
* hierarchies replace the primary annotation on Ai with the lowest possible annotation
* (ensuring that it won't be the LUB unless there are no other constraints, or all other
* constraints imply the bottom annotation is the LUB). Note: Even if we choose bottom as
* the lub here, the assignment context may raise this annotation.
*/
final Entry<AnnotatedTypeMirror, AnnotationMirrorSet> head = typesIter.next();
AnnotatedTypeMirror lubType = groundMissingHierarchies(head, lowerBoundAnnos);
AnnotatedTypeMirror nextType = null;
while (typesIter.hasNext()) {
nextType = groundMissingHierarchies(typesIter.next(), lowerBoundAnnos);
if (lubType.getKind().isPrimitive()) {
if (!nextType.getKind().isPrimitive()) {
lubType = typeFactory.getBoxedType((AnnotatedPrimitiveType) lubType);
}
} else if (nextType.getKind().isPrimitive()) {
if (!lubType.getKind().isPrimitive()) {
nextType = typeFactory.getBoxedType((AnnotatedPrimitiveType) nextType);
}
}
lubType = AnnotatedTypes.leastUpperBound(typeFactory, lubType, nextType);
}
return lubType;
}
Aggregations