use of org.checkerframework.framework.util.AnnotationMirrorMap 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<Map.Entry<AnnotatedTypeMirror, AnnotationMirrorSet>> typesIter = types.entrySet().iterator();
if (!typesIter.hasNext()) {
throw new BugInCF("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 Map.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;
}
use of org.checkerframework.framework.util.AnnotationMirrorMap 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 Map.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.AnnotationMirrorMap in project checker-framework by typetools.
the class GlbUtil method glbAll.
/**
* Note: This method can be improved for wildcards and type variables.
*
* @return the greatest lower bound of typeMirrors. If any of the type mirrors are incomparable,
* use an AnnotatedNullType that will contain the greatest lower bounds of the primary
* annotations of typeMirrors.
*/
public static AnnotatedTypeMirror glbAll(final Map<AnnotatedTypeMirror, AnnotationMirrorSet> typeMirrors, final AnnotatedTypeFactory typeFactory) {
final QualifierHierarchy qualifierHierarchy = typeFactory.getQualifierHierarchy();
if (typeMirrors.isEmpty()) {
return null;
}
// dtermine the greatest lower bounds for the primary annotations
AnnotationMirrorMap<AnnotationMirror> glbPrimaries = new AnnotationMirrorMap<>();
for (Map.Entry<AnnotatedTypeMirror, AnnotationMirrorSet> tmEntry : typeMirrors.entrySet()) {
final AnnotationMirrorSet typeAnnoHierarchies = tmEntry.getValue();
final AnnotatedTypeMirror type = tmEntry.getKey();
for (AnnotationMirror top : typeAnnoHierarchies) {
// TODO: When all of the typeMirrors are either wildcards or type variables than the
// greatest lower bound should involve handling the bounds individually rather than
// using the effective annotation. We are doing this for expediency.
final AnnotationMirror typeAnno = type.getEffectiveAnnotationInHierarchy(top);
final AnnotationMirror currentAnno = glbPrimaries.get(top);
if (typeAnno != null && currentAnno != null) {
glbPrimaries.put(top, qualifierHierarchy.greatestLowerBound(currentAnno, typeAnno));
} else if (typeAnno != null) {
glbPrimaries.put(top, typeAnno);
}
}
}
final List<AnnotatedTypeMirror> glbTypes = new ArrayList<>();
// create a copy of all of the types and apply the glb primary annotation
final AnnotationMirrorSet values = new AnnotationMirrorSet(glbPrimaries.values());
for (AnnotatedTypeMirror type : typeMirrors.keySet()) {
if (type.getKind() != TypeKind.TYPEVAR || !qualifierHierarchy.isSubtype(type.getEffectiveAnnotations(), values)) {
final AnnotatedTypeMirror copy = type.deepCopy();
copy.replaceAnnotations(values);
glbTypes.add(copy);
} else {
// if the annotations came from the upper bound of this typevar
// we do NOT want to place them as primary annotations (and destroy the
// type vars lower bound)
glbTypes.add(type);
}
}
final TypeHierarchy typeHierarchy = typeFactory.getTypeHierarchy();
// sort placing supertypes first
sortForGlb(glbTypes, typeFactory);
// find the lowest type in the list that is not an AnnotatedNullType
AnnotatedTypeMirror glbType = glbTypes.get(0);
int index = 1;
while (index < glbTypes.size()) {
// NULL types
if (glbType.getKind() != TypeKind.NULL) {
glbType = glbTypes.get(index);
}
index += 1;
}
// if the lowest type is a subtype of all glbTypes then it is the GLB, otherwise there are two
// types in glbTypes that are incomparable and we need to use bottom (AnnotatedNullType)
boolean incomparable = false;
for (final AnnotatedTypeMirror type : glbTypes) {
if (!incomparable && type.getKind() != TypeKind.NULL && (!TypesUtils.isErasedSubtype(glbType.getUnderlyingType(), type.getUnderlyingType(), typeFactory.getChecker().getTypeUtils()) || !typeHierarchy.isSubtype(glbType, type))) {
incomparable = true;
}
}
// we had two incomparable types in glbTypes
if (incomparable) {
return createBottom(typeFactory, glbType.getEffectiveAnnotations());
}
return glbType;
}
use of org.checkerframework.framework.util.AnnotationMirrorMap in project checker-framework by typetools.
the class DefaultQualifierPolymorphism method replace.
@Override
protected void replace(AnnotatedTypeMirror type, AnnotationMirrorMap<AnnotationMirror> replacements) {
for (Map.Entry<AnnotationMirror, AnnotationMirror> pqentry : replacements.entrySet()) {
AnnotationMirror poly = pqentry.getKey();
if (type.hasAnnotation(poly)) {
type.removeAnnotation(poly);
AnnotationMirror qual;
if (polyInstantiationForQualifierParameter.containsKey(poly)) {
qual = polyInstantiationForQualifierParameter.get(poly);
} else {
qual = pqentry.getValue();
}
type.replaceAnnotation(qual);
}
}
}
Aggregations