use of org.checkerframework.framework.type.QualifierHierarchy in project checker-framework by typetools.
the class LubGlbChecker method initChecker.
@Override
public void initChecker() {
super.initChecker();
Elements elements = processingEnv.getElementUtils();
A = AnnotationBuilder.fromClass(elements, A.class);
B = AnnotationBuilder.fromClass(elements, B.class);
C = AnnotationBuilder.fromClass(elements, C.class);
D = AnnotationBuilder.fromClass(elements, D.class);
E = AnnotationBuilder.fromClass(elements, E.class);
F = AnnotationBuilder.fromClass(elements, F.class);
POLY = AnnotationBuilder.fromClass(elements, Poly.class);
QualifierHierarchy qh = ((BaseTypeVisitor<?>) visitor).getTypeFactory().getQualifierHierarchy();
// System.out.println("LUB of D and E: " + qh.leastUpperBound(D, E));
assert AnnotationUtils.areSame(qh.leastUpperBound(D, E), C) : "LUB of D and E is not C!";
// System.out.println("LUB of E and D: " + qh.leastUpperBound(E, D));
assert AnnotationUtils.areSame(qh.leastUpperBound(E, D), C) : "LUB of E and D is not C!";
// System.out.println("GLB of B and C: " + qh.greatestLowerBound(B, C));
assert AnnotationUtils.areSame(qh.greatestLowerBound(B, C), D) : "GLB of B and C is not D!";
// System.out.println("GLB of C and B: " + qh.greatestLowerBound(C, B));
assert AnnotationUtils.areSame(qh.greatestLowerBound(C, B), D) : "GLB of C and B is not D!";
assert AnnotationUtils.areSame(qh.greatestLowerBound(POLY, B), F) : "GLB of POLY and B is not F!";
assert AnnotationUtils.areSame(qh.greatestLowerBound(POLY, F), F) : "GLB of POLY and F is not F!";
assert AnnotationUtils.areSame(qh.greatestLowerBound(POLY, A), POLY) : "GLB of POLY and A is not POLY!";
assert AnnotationUtils.areSame(qh.leastUpperBound(POLY, B), A) : "LUB of POLY and B is not A!";
assert AnnotationUtils.areSame(qh.leastUpperBound(POLY, F), POLY) : "LUB of POLY and F is not POLY!";
assert AnnotationUtils.areSame(qh.leastUpperBound(POLY, A), A) : "LUB of POLY and A is not A!";
}
use of org.checkerframework.framework.type.QualifierHierarchy in project checker-framework by typetools.
the class QualifierDefaults method addUncheckedStandardDefaults.
/**
* Add standard unchecked defaults that do not conflict with previously added defaults.
*/
public void addUncheckedStandardDefaults() {
QualifierHierarchy qualHierarchy = this.atypeFactory.getQualifierHierarchy();
Set<? extends AnnotationMirror> tops = qualHierarchy.getTopAnnotations();
Set<? extends AnnotationMirror> bottoms = qualHierarchy.getBottomAnnotations();
for (TypeUseLocation loc : standardUncheckedDefaultsTop) {
// Only add standard defaults in locations where a default has not be specified
for (AnnotationMirror top : tops) {
if (!conflictsWithExistingDefaults(uncheckedCodeDefaults, top, loc)) {
addUncheckedCodeDefault(top, loc);
}
}
}
for (TypeUseLocation loc : standardUncheckedDefaultsBottom) {
for (AnnotationMirror bottom : bottoms) {
// Only add standard defaults in locations where a default has not be specified
if (!conflictsWithExistingDefaults(uncheckedCodeDefaults, bottom, loc)) {
addUncheckedCodeDefault(bottom, loc);
}
}
}
}
use of org.checkerframework.framework.type.QualifierHierarchy in project checker-framework by typetools.
the class DefaultTypeArgumentInference method clampToLowerBound.
/**
* If we have inferred a type argument from the supertype constraints and this type argument is
* BELOW the lower bound, make it AT the lower bound
*
* <p>e.g.
*
* <pre>{@code
* <@Initialized T extends @Initialized Object> void id(T t) { return t; }
* id(null);
*
* // The invocation of id will result in a type argument with primary annotations of @FBCBottom @Nullable
* // but this is below the lower bound of T in the initialization hierarchy so instead replace
* //@FBCBottom with @Initialized
*
* // This should happen ONLY with supertype constraints because raising the primary annotation would still
* // be valid for these constraints (since we just LUB the arguments involved) but would violate any
* // equality constraints
* }</pre>
*
* TODO: NOTE WE ONLY DO THIS FOR InferredType results for now but we should probably include
* targest as well
*
* @param fromArgSupertypes types inferred from LUBbing types from the arguments to the formal
* parameters
* @param targetDeclarations the declared types of the type parameters whose arguments are being
* inferred
*/
private void clampToLowerBound(InferenceResult fromArgSupertypes, List<AnnotatedTypeVariable> targetDeclarations, AnnotatedTypeFactory typeFactory) {
final QualifierHierarchy qualifierHierarchy = typeFactory.getQualifierHierarchy();
final AnnotationMirrorSet tops = new AnnotationMirrorSet(qualifierHierarchy.getTopAnnotations());
for (AnnotatedTypeVariable targetDecl : targetDeclarations) {
InferredValue inferred = fromArgSupertypes.get(targetDecl.getUnderlyingType());
if (inferred != null && inferred instanceof InferredType) {
final AnnotatedTypeMirror lowerBoundAsArgument = targetDecl.getLowerBound();
for (AnnotationMirror top : tops) {
final AnnotationMirror lowerBoundAnno = lowerBoundAsArgument.getEffectiveAnnotationInHierarchy(top);
final AnnotationMirror argAnno = ((InferredType) inferred).type.getEffectiveAnnotationInHierarchy(top);
if (qualifierHierarchy.isSubtype(argAnno, lowerBoundAnno)) {
((InferredType) inferred).type.replaceAnnotation(lowerBoundAnno);
}
}
}
}
}
use of org.checkerframework.framework.type.QualifierHierarchy 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.type.QualifierHierarchy in project checker-framework by typetools.
the class GlbUtil method sortForGlb.
/**
* Sort the list of type mirrors, placing supertypes first and subtypes last.
*
* <p>E.g. the list: {@code ArrayList<String>, List<String>, AbstractList<String>} becomes:
* {@code List<String>, AbstractList<String>, ArrayList<String>}
*/
public static void sortForGlb(final List<? extends AnnotatedTypeMirror> typeMirrors, final AnnotatedTypeFactory typeFactory) {
final QualifierHierarchy qualifierHierarchy = typeFactory.getQualifierHierarchy();
final Types types = typeFactory.getProcessingEnv().getTypeUtils();
Collections.sort(typeMirrors, new Comparator<AnnotatedTypeMirror>() {
@Override
public int compare(AnnotatedTypeMirror type1, AnnotatedTypeMirror type2) {
final TypeMirror underlyingType1 = type1.getUnderlyingType();
final TypeMirror underlyingType2 = type2.getUnderlyingType();
if (types.isSameType(underlyingType1, underlyingType2)) {
return compareAnnotations(qualifierHierarchy, type1, type2);
}
if (types.isSubtype(underlyingType1, underlyingType2)) {
return 1;
}
// if they're incomparable or type2 is a subtype of type1
return -1;
}
private int compareAnnotations(final QualifierHierarchy qualHierarchy, final AnnotatedTypeMirror type1, final AnnotatedTypeMirror type2) {
if (AnnotationUtils.areSame(type1.getAnnotations(), type2.getAnnotations())) {
return 0;
}
if (qualHierarchy.isSubtype(type1.getAnnotations(), type2.getAnnotations())) {
return 1;
} else {
return -1;
}
}
});
}
Aggregations