use of javax.lang.model.type.TypeVariable in project checker-framework by typetools.
the class TypeArgInferenceUtil method methodTypeToTargets.
/**
* Given an AnnotatedExecutableType return a set of type variables that represents the generic
* type parameters of that method.
*/
public static Set<TypeVariable> methodTypeToTargets(final AnnotatedExecutableType methodType) {
final List<AnnotatedTypeVariable> annotatedTypeVars = methodType.getTypeVariables();
final Set<TypeVariable> targets = new LinkedHashSet<>(annotatedTypeVars.size());
for (final AnnotatedTypeVariable atv : annotatedTypeVars) {
targets.add((TypeVariable) TypeAnnotationUtils.unannotatedType(atv.getUnderlyingType()));
}
return targets;
}
use of javax.lang.model.type.TypeVariable in project checker-framework by typetools.
the class EqualitiesSolver method rewriteWithInferredType.
/**
* Let Ti be a target type parameter. When we reach this method we have inferred an argument, Ai,
* for Ti.
*
* <p>However, there still may be constraints of the form {@literal Ti = Tj}, {@literal Ti <: Tj},
* {@literal Tj <: Ti} in the constraint map. In this case we need to replace Ti with the type.
* That is, they become {@literal Ai = Tj}, {@literal Ai <: Tj}, and {@literal Tj <: Ai}
*
* <p>To do this, we find the TargetConstraints for Tj and add these constraints to the
* appropriate map in TargetConstraints. We can then clear the constraints for the current target
* since we have inferred a type.
*
* @param target the target for which we have inferred a concrete type argument
* @param type the type inferred
* @param constraints the constraints that are side-effected by this method
*/
private void rewriteWithInferredType(@FindDistinct final TypeVariable target, final AnnotatedTypeMirror type, final ConstraintMap constraints) {
final TargetConstraints targetRecord = constraints.getConstraints(target);
final Map<TypeVariable, AnnotationMirrorSet> equivalentTargets = targetRecord.equalities.targets;
// hierarchies as the inferred type
for (final Map.Entry<TypeVariable, AnnotationMirrorSet> eqEntry : equivalentTargets.entrySet()) {
constraints.addTypeEqualities(eqEntry.getKey(), type, eqEntry.getValue());
}
for (TypeVariable otherTarget : constraints.getTargets()) {
if (otherTarget != target) {
final TargetConstraints record = constraints.getConstraints(otherTarget);
// each target that was equivalent to this one needs to be equivalent in the same
// hierarchies as the inferred type
final AnnotationMirrorSet hierarchies = record.equalities.targets.get(target);
if (hierarchies != null) {
record.equalities.targets.remove(target);
constraints.addTypeEqualities(otherTarget, type, hierarchies);
}
// otherTypes may have AnnotatedTypeVariables of type target, run substitution on
// these with type
Map<AnnotatedTypeMirror, AnnotationMirrorSet> toIterate = new LinkedHashMap<>(record.equalities.types);
record.equalities.types.clear();
for (AnnotatedTypeMirror otherType : toIterate.keySet()) {
final AnnotatedTypeMirror copy = TypeArgInferenceUtil.substitute(target, type, otherType);
final AnnotationMirrorSet otherHierarchies = toIterate.get(otherType);
record.equalities.types.put(copy, otherHierarchies);
}
}
}
for (TypeVariable otherTarget : constraints.getTargets()) {
if (otherTarget != target) {
final TargetConstraints record = constraints.getConstraints(otherTarget);
// each target that was equivalent to this one needs to be equivalent in the same
// hierarchies as the inferred type
final AnnotationMirrorSet hierarchies = record.supertypes.targets.get(target);
if (hierarchies != null) {
record.supertypes.targets.remove(target);
constraints.addTypeEqualities(otherTarget, type, hierarchies);
}
// otherTypes may have AnnotatedTypeVariables of type target, run substitution on
// these with type
Map<AnnotatedTypeMirror, AnnotationMirrorSet> toIterate = new LinkedHashMap<>(record.supertypes.types);
record.supertypes.types.clear();
for (AnnotatedTypeMirror otherType : toIterate.keySet()) {
final AnnotatedTypeMirror copy = TypeArgInferenceUtil.substitute(target, type, otherType);
final AnnotationMirrorSet otherHierarchies = toIterate.get(otherType);
record.supertypes.types.put(copy, otherHierarchies);
}
}
}
targetRecord.equalities.clear();
targetRecord.supertypes.clear();
}
use of javax.lang.model.type.TypeVariable in project checker-framework by typetools.
the class EqualitiesSolver method updateTargetsWithPartiallyInferredType.
// If we determined that this target T1 is equal to a type ATM in hierarchies @A,@B,@C
// for each of those hierarchies, if a target is equal to T1 in that hierarchy it is also equal
// to ATM.
// e.g.
// if : T1 == @A @B @C ATM in only the A,B hierarchies
// and T1 == T2 only in @A hierarchy
//
// then T2 == @A @B @C only in the @A hierarchy
//
public boolean updateTargetsWithPartiallyInferredType(final Equalities equalities, ConstraintMap constraintMap, AnnotatedTypeFactory typeFactory) {
boolean updated = false;
if (!equalities.types.isEmpty()) {
if (equalities.types.size() != 1) {
throw new BugInCF("Equalities should have at most 1 constraint.");
}
Map.Entry<AnnotatedTypeMirror, AnnotationMirrorSet> remainingTypeEquality;
remainingTypeEquality = equalities.types.entrySet().iterator().next();
final AnnotatedTypeMirror remainingType = remainingTypeEquality.getKey();
final AnnotationMirrorSet remainingHierarchies = remainingTypeEquality.getValue();
// update targets
for (Map.Entry<TypeVariable, AnnotationMirrorSet> targetToHierarchies : equalities.targets.entrySet()) {
final TypeVariable equalTarget = targetToHierarchies.getKey();
final AnnotationMirrorSet hierarchies = targetToHierarchies.getValue();
final AnnotationMirrorSet equalTypeHierarchies = new AnnotationMirrorSet(remainingHierarchies);
equalTypeHierarchies.retainAll(hierarchies);
final Map<AnnotatedTypeMirror, AnnotationMirrorSet> otherTargetsEqualTypes = constraintMap.getConstraints(equalTarget).equalities.types;
AnnotationMirrorSet equalHierarchies = otherTargetsEqualTypes.get(remainingType);
if (equalHierarchies == null) {
equalHierarchies = new AnnotationMirrorSet(equalTypeHierarchies);
otherTargetsEqualTypes.put(remainingType, equalHierarchies);
updated = true;
} else {
final int size = equalHierarchies.size();
equalHierarchies.addAll(equalTypeHierarchies);
updated = size == equalHierarchies.size();
}
}
}
return updated;
}
use of javax.lang.model.type.TypeVariable in project checker-framework by typetools.
the class EqualitiesSolver method rewriteWithInferredTarget.
/**
* Let Ti be a target type parameter. When we reach this method we have inferred that Ti has the
* exact same argument as another target Tj
*
* <p>Therefore, we want to stop solving for Ti and instead wait till we solve for Tj and use that
* result.
*
* <p>Let ATM be any annotated type mirror and Tk be a target type parameter where k != i and k !=
* j Even though we've inferred Ti = Tj, there still may be constraints of the form Ti = ATM or
* {@literal Ti <: Tk} These constraints are still useful for inferring a argument for Ti/Tj. So,
* we replace Ti in these constraints with Tj and place those constraints in the TargetConstraints
* object for Tj.
*
* <p>We then clear the constraints for Ti.
*
* @param target the target for which we know another target is exactly equal to this target
* @param inferredTarget the other target inferred to be equal
* @param constraints the constraints that are side-effected by this method
* @param typeFactory type factory
*/
private void rewriteWithInferredTarget(@FindDistinct final TypeVariable target, @FindDistinct final TypeVariable inferredTarget, final ConstraintMap constraints, final AnnotatedTypeFactory typeFactory) {
final TargetConstraints targetRecord = constraints.getConstraints(target);
final Map<AnnotatedTypeMirror, AnnotationMirrorSet> equivalentTypes = targetRecord.equalities.types;
final Map<AnnotatedTypeMirror, AnnotationMirrorSet> supertypes = targetRecord.supertypes.types;
// to the inferred target
for (final Map.Entry<AnnotatedTypeMirror, AnnotationMirrorSet> eqEntry : equivalentTypes.entrySet()) {
constraints.addTypeEqualities(inferredTarget, eqEntry.getKey(), eqEntry.getValue());
}
for (final Map.Entry<AnnotatedTypeMirror, AnnotationMirrorSet> superEntry : supertypes.entrySet()) {
constraints.addTypeSupertype(inferredTarget, superEntry.getKey(), superEntry.getValue());
}
for (TypeVariable otherTarget : constraints.getTargets()) {
if (otherTarget != target && otherTarget != inferredTarget) {
final TargetConstraints record = constraints.getConstraints(otherTarget);
// each target that was equivalent to this one needs to be equivalent in the same
// hierarchies as the inferred target
final AnnotationMirrorSet hierarchies = record.equalities.targets.get(target);
if (hierarchies != null) {
record.equalities.targets.remove(target);
constraints.addTargetEquality(otherTarget, inferredTarget, hierarchies);
}
// otherTypes may have AnnotatedTypeVariables of type target, run substitution on
// these with type
Map<AnnotatedTypeMirror, AnnotationMirrorSet> toIterate = new LinkedHashMap<>(record.equalities.types);
record.equalities.types.clear();
for (AnnotatedTypeMirror otherType : toIterate.keySet()) {
final AnnotatedTypeMirror copy = TypeArgInferenceUtil.substitute(target, createAnnotatedTypeVar(target, typeFactory), otherType);
final AnnotationMirrorSet otherHierarchies = toIterate.get(otherType);
record.equalities.types.put(copy, otherHierarchies);
}
}
}
for (TypeVariable otherTarget : constraints.getTargets()) {
if (otherTarget != target && otherTarget != inferredTarget) {
final TargetConstraints record = constraints.getConstraints(otherTarget);
final AnnotationMirrorSet hierarchies = record.supertypes.targets.get(target);
if (hierarchies != null) {
record.supertypes.targets.remove(target);
constraints.addTargetSupertype(otherTarget, inferredTarget, hierarchies);
}
// otherTypes may have AnnotatedTypeVariables of type target, run substitution on
// these with type
Map<AnnotatedTypeMirror, AnnotationMirrorSet> toIterate = new LinkedHashMap<>(record.supertypes.types);
record.supertypes.types.clear();
for (AnnotatedTypeMirror otherType : toIterate.keySet()) {
final AnnotatedTypeMirror copy = TypeArgInferenceUtil.substitute(target, createAnnotatedTypeVar(target, typeFactory), otherType);
final AnnotationMirrorSet otherHierarchies = toIterate.get(otherType);
record.supertypes.types.put(copy, otherHierarchies);
}
}
}
targetRecord.equalities.clear();
targetRecord.supertypes.clear();
}
use of javax.lang.model.type.TypeVariable 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.isEmpty()) {
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;
}
Aggregations