use of org.checkerframework.framework.util.typeinference.constraint.TUConstraint in project checker-framework by typetools.
the class DefaultTypeArgumentInference method addConstraintsBetweenTargets.
/**
* Declarations of the form: {@code <A, B extends A>} implies a TUConstraint of {@code B <: A}.
* Add these to the constraint list.
*/
public void addConstraintsBetweenTargets(Set<TUConstraint> constraints, Set<TypeVariable> targets, boolean asSubtype, AnnotatedTypeFactory typeFactory) {
final Types types = typeFactory.getProcessingEnv().getTypeUtils();
final List<TypeVariable> targetList = new ArrayList<>(targets);
final Map<TypeVariable, AnnotatedTypeVariable> paramDeclarations = new HashMap<>();
for (int i = 0; i < targetList.size(); i++) {
final TypeVariable earlierTarget = targetList.get(i);
for (int j = i + 1; j < targetList.size(); j++) {
final TypeVariable laterTarget = targetList.get(j);
if (types.isSameType(earlierTarget.getUpperBound(), laterTarget)) {
final AnnotatedTypeVariable headDecl = addOrGetDeclarations(earlierTarget, typeFactory, paramDeclarations);
final AnnotatedTypeVariable nextDecl = addOrGetDeclarations(laterTarget, typeFactory, paramDeclarations);
if (asSubtype) {
constraints.add(new TSubU(headDecl, nextDecl));
} else {
constraints.add(new TSuperU(nextDecl, headDecl));
}
} else if (types.isSameType(laterTarget.getUpperBound(), earlierTarget)) {
final AnnotatedTypeVariable headDecl = addOrGetDeclarations(earlierTarget, typeFactory, paramDeclarations);
final AnnotatedTypeVariable nextDecl = addOrGetDeclarations(laterTarget, typeFactory, paramDeclarations);
if (asSubtype) {
constraints.add(new TSubU(nextDecl, headDecl));
} else {
constraints.add(new TSuperU(headDecl, nextDecl));
}
}
}
}
}
use of org.checkerframework.framework.util.typeinference.constraint.TUConstraint in project checker-framework by typetools.
the class DefaultTypeArgumentInference method inferFromArguments.
/**
* Step 2. Infer type arguments from the equality (TisU) and the supertype (TSuperU) constraints
* of the methods arguments.
*/
private Pair<InferenceResult, InferenceResult> inferFromArguments(final AnnotatedTypeFactory typeFactory, final Set<AFConstraint> afArgumentConstraints, final Set<TypeVariable> targets) {
Set<TUConstraint> tuArgConstraints = afToTuConstraints(afArgumentConstraints, targets);
addConstraintsBetweenTargets(tuArgConstraints, targets, false, typeFactory);
ConstraintMap argConstraints = constraintMapBuilder.build(targets, tuArgConstraints, typeFactory);
InferenceResult inferredFromArgEqualities = equalitiesSolver.solveEqualities(targets, argConstraints, typeFactory);
Set<TypeVariable> remainingTargets = inferredFromArgEqualities.getRemainingTargets(targets, true);
InferenceResult fromSupertypes = supertypesSolver.solveFromSupertypes(remainingTargets, argConstraints, typeFactory);
InferenceResult fromSubtypes = subtypesSolver.solveFromSubtypes(remainingTargets, argConstraints, typeFactory);
fromSupertypes.mergeSubordinate(fromSubtypes);
return Pair.of(inferredFromArgEqualities, fromSupertypes);
}
use of org.checkerframework.framework.util.typeinference.constraint.TUConstraint in project checker-framework by typetools.
the class DefaultTypeArgumentInference method createAssignmentConstraints.
/**
* The first half of Step 6.
*
* <p>This method creates constraints:
*
* <ul>
* <li>between the bounds of types that are already inferred and their inferred arguments
* <li>between the assignment context and the return type of the method (with the previously
* inferred arguments substituted into these constraints)
* </ul>
*/
public ConstraintMap createAssignmentConstraints(final AnnotatedTypeMirror assignedTo, final AnnotatedTypeMirror boxedReturnType, final AnnotatedExecutableType methodType, final Set<AFConstraint> afArgumentConstraints, final Map<TypeVariable, AnnotatedTypeMirror> inferredArgs, final Set<TypeVariable> targets, final AnnotatedTypeFactory typeFactory) {
final ArrayDeque<AFConstraint> assignmentAfs = new ArrayDeque<>(2 * methodType.getTypeVariables().size() + afArgumentConstraints.size());
for (AnnotatedTypeVariable typeParam : methodType.getTypeVariables()) {
final TypeVariable target = typeParam.getUnderlyingType();
final AnnotatedTypeMirror inferredType = inferredArgs.get(target);
// the lower bound for all uninferred types Tu: Tu >> Bi and Lu >> Tu
if (inferredType != null) {
assignmentAfs.add(new A2F(inferredType, typeParam.getUpperBound()));
assignmentAfs.add(new F2A(typeParam.getLowerBound(), inferredType));
} else {
assignmentAfs.add(new F2A(typeParam, typeParam.getUpperBound()));
assignmentAfs.add(new A2F(typeParam.getLowerBound(), typeParam));
}
}
for (AFConstraint argConstraint : afArgumentConstraints) {
if (argConstraint instanceof F2A) {
assignmentAfs.add(argConstraint);
}
}
ArrayDeque<AFConstraint> substitutedAssignmentConstraints = new ArrayDeque<>(assignmentAfs.size() + 1);
for (AFConstraint afConstraint : assignmentAfs) {
substitutedAssignmentConstraints.add(afConstraint.substitute(inferredArgs));
}
final AnnotatedTypeMirror substitutedReturnType = TypeArgInferenceUtil.substitute(inferredArgs, boxedReturnType);
substitutedAssignmentConstraints.add(new F2A(substitutedReturnType, assignedTo));
final Set<AFConstraint> reducedConstraints = new LinkedHashSet<>();
reduceAfConstraints(typeFactory, reducedConstraints, substitutedAssignmentConstraints, targets);
final Set<TUConstraint> tuAssignmentConstraints = afToTuConstraints(reducedConstraints, targets);
addConstraintsBetweenTargets(tuAssignmentConstraints, targets, true, typeFactory);
return constraintMapBuilder.build(targets, tuAssignmentConstraints, typeFactory);
}
use of org.checkerframework.framework.util.typeinference.constraint.TUConstraint in project checker-framework by typetools.
the class DefaultTypeArgumentInference method inferFromAssignmentEqualities.
/**
* Step 3. Infer type arguments from the equality constraints of the assignment context.
*/
private InferenceResult inferFromAssignmentEqualities(final AnnotatedTypeMirror assignedTo, final AnnotatedTypeMirror boxedReturnType, final Set<TypeVariable> targets, final AnnotatedTypeFactory typeFactory) {
Set<FIsA> afInitialAssignmentConstraints = createInitialAssignmentConstraints(assignedTo, boxedReturnType, typeFactory, targets);
Set<TUConstraint> tuInitialAssignmentConstraints = afToTuConstraints(afInitialAssignmentConstraints, targets);
ConstraintMap initialAssignmentConstraints = constraintMapBuilder.build(targets, tuInitialAssignmentConstraints, typeFactory);
return equalitiesSolver.solveEqualities(targets, initialAssignmentConstraints, typeFactory);
}
use of org.checkerframework.framework.util.typeinference.constraint.TUConstraint 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 (!typeFactory.types.isSameType(TypeAnnotationUtils.unannotatedType(typeT.getUnderlyingType()), 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