use of org.checkerframework.framework.util.AnnotationMirrorSet 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 (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.getContext().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.AnnotationMirrorSet in project checker-framework by typetools.
the class ConstraintMap method addTargetSupertype.
/**
* Add a constraint indicating that target is a supertype of subtype in the given qualifier
* hierarchies
*
* @param hierarchies a set of TOP annotations
*/
public void addTargetSupertype(final TypeVariable target, final TypeVariable subtype, AnnotationMirrorSet hierarchies) {
final Supertypes supertypes = targetToRecords.get(target).supertypes;
final AnnotationMirrorSet supertypeTops = supertypes.targets.get(subtype);
if (supertypeTops == null) {
supertypes.targets.put(subtype, new AnnotationMirrorSet(hierarchies));
} else {
supertypeTops.addAll(hierarchies);
}
}
use of org.checkerframework.framework.util.AnnotationMirrorSet in project checker-framework by typetools.
the class ConstraintMap method addPrimarySupertype.
/**
* Add a constraint indicating that target's primary annotations are subtypes of the given
* annotations
*/
public void addPrimarySupertype(final TypeVariable target, QualifierHierarchy qualifierHierarchy, final AnnotationMirrorSet annos) {
final Supertypes supertypes = targetToRecords.get(target).supertypes;
for (final AnnotationMirror anno : annos) {
final AnnotationMirror top = qualifierHierarchy.getTopAnnotation(anno);
AnnotationMirrorSet entries = supertypes.primaries.get(top);
if (entries == null) {
entries = new AnnotationMirrorSet();
supertypes.primaries.put(top, entries);
}
entries.add(anno);
}
}
use of org.checkerframework.framework.util.AnnotationMirrorSet in project checker-framework by typetools.
the class ConstraintMap method addTypeEqualities.
/**
* Add a constraint indicating that target is equal to type in the given hierarchies
*
* @param hierarchies a set of TOP annotations
*/
public void addTypeEqualities(TypeVariable target, AnnotatedTypeMirror type, AnnotationMirrorSet hierarchies) {
final Equalities equalities = targetToRecords.get(target).equalities;
final AnnotationMirrorSet equalityTops = equalities.types.get(type);
if (equalityTops == null) {
equalities.types.put(type, new AnnotationMirrorSet(hierarchies));
} else {
equalityTops.addAll(hierarchies);
}
}
use of org.checkerframework.framework.util.AnnotationMirrorSet in project checker-framework by typetools.
the class ConstraintMapBuilder method build.
/**
* Let Ti be a the ith target being inferred Let ATV(i) be the annotated type variable that
* represents as use of Ti which may or may not have primary annotations. Let ATM be an
* annotated type mirror that may or may not be target Tx, or have a component target Tx Let Ai
* be the type argument we are trying to infer for Ti
*
* <p>We have a set of constraints of the form: {@code ATV(i) <?> ATM}
*
* <p>Where {@code <?>} is either a subtype ({@code <:}), supertype ({@code :>}), or equality
* relationship ({@code =}).
*
* <p>Regardless of what {@code <?>} is, a constraint will only imply constraints on Ai in a
* given hierarchy if ATV(i) does NOT have a primary annotation in that hierarchy. That is:
*
* <p>E.g. Let ATV(i) be @NonNull Ti, the constraints @NonNull Ti = @NonNull @Initialized String
* does not imply any primary annotation in the Nullness hierarchy for type argument Ai because
* the Annotated type mirror has a primary annotation in the NUllness hierarchy.
*
* <p>However, it does imply that Ai has a primary annotation of @Initialized since ATV(i) has
* no primary annotation in the initialization hierarchy.
*
* <p>Note, constraints come in 2 forms:
*
* <ul>
* <li>between a target and a concrete AnnotatedTypeMirror. E.g., As seen above {@code
* (@NonNull Ti = @NonNull @Initialized String)}
* <li>between two targets E.g., {@code (@NonNull Ti = Tj)}
* </ul>
*/
public ConstraintMap build(Set<TypeVariable> targets, Set<TUConstraint> constraints, AnnotatedTypeFactory typeFactory) {
final QualifierHierarchy qualifierHierarchy = typeFactory.getQualifierHierarchy();
final AnnotationMirrorSet tops = new AnnotationMirrorSet(qualifierHierarchy.getTopAnnotations());
final ConstraintMap result = new ConstraintMap(targets);
final AnnotationMirrorSet tAnnos = new AnnotationMirrorSet();
final AnnotationMirrorSet uAnnos = new AnnotationMirrorSet();
final AnnotationMirrorSet hierarchiesInRelation = new AnnotationMirrorSet();
for (TUConstraint constraint : constraints) {
tAnnos.clear();
uAnnos.clear();
hierarchiesInRelation.clear();
final AnnotatedTypeVariable typeT = constraint.typeVariable;
final AnnotatedTypeMirror typeU = constraint.relatedType;
// The inferred type of T should be T.
if (!constraint.uIsArg && typeU.getKind() == TypeKind.TYPEVAR && targets.contains((TypeVariable) TypeAnnotationUtils.unannotatedType(typeU.getUnderlyingType()))) {
if (typeT.getAnnotations().isEmpty() && typeU.getAnnotations().isEmpty()) {
hierarchiesInRelation.addAll(tops);
} else {
for (AnnotationMirror top : tops) {
final AnnotationMirror tAnno = typeT.getAnnotationInHierarchy(top);
final AnnotationMirror uAnno = typeU.getAnnotationInHierarchy(top);
if (tAnno == null) {
if (uAnno == null) {
hierarchiesInRelation.add(top);
} else {
tAnnos.add(uAnno);
}
} else {
if (uAnno == null) {
uAnnos.add(tAnno);
} else {
// This tells us nothing, they both should be equal but either way
// we gain no information if both type vars have annotations
}
}
}
// This case also covers the case where i = j.
if (!tAnnos.isEmpty()) {
addToPrimaryRelationship((TypeVariable) TypeAnnotationUtils.unannotatedType(typeT.getUnderlyingType()), constraint, result, tAnnos, qualifierHierarchy);
}
if (!uAnnos.isEmpty()) {
addToPrimaryRelationship((TypeVariable) TypeAnnotationUtils.unannotatedType(typeU.getUnderlyingType()), constraint, result, uAnnos, qualifierHierarchy);
}
}
// <?> Tj and i != j)
if (!TypeAnnotationUtils.unannotatedType(typeT.getUnderlyingType()).equals(TypeAnnotationUtils.unannotatedType(typeU.getUnderlyingType()))) {
addToTargetRelationship((TypeVariable) TypeAnnotationUtils.unannotatedType(typeT.getUnderlyingType()), (TypeVariable) TypeAnnotationUtils.unannotatedType(typeU.getUnderlyingType()), result, constraint, hierarchiesInRelation);
}
} else {
for (AnnotationMirror top : tops) {
final AnnotationMirror tAnno = typeT.getAnnotationInHierarchy(top);
if (tAnno == null) {
hierarchiesInRelation.add(top);
}
}
addToTypeRelationship((TypeVariable) TypeAnnotationUtils.unannotatedType(typeT.getUnderlyingType()), typeU, result, constraint, hierarchiesInRelation);
}
}
return result;
}
Aggregations