Search in sources :

Example 1 with TUConstraint

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));
                }
            }
        }
    }
}
Also used : Types(javax.lang.model.util.Types) AnnotatedTypes(org.checkerframework.framework.util.AnnotatedTypes) TypeVariable(javax.lang.model.type.TypeVariable) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) TSuperU(org.checkerframework.framework.util.typeinference.constraint.TSuperU) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) AFConstraint(org.checkerframework.framework.util.typeinference.constraint.AFConstraint) TUConstraint(org.checkerframework.framework.util.typeinference.constraint.TUConstraint) TSubU(org.checkerframework.framework.util.typeinference.constraint.TSubU)

Example 2 with TUConstraint

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);
}
Also used : TypeVariable(javax.lang.model.type.TypeVariable) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) ConstraintMap(org.checkerframework.framework.util.typeinference.solver.ConstraintMap) InferenceResult(org.checkerframework.framework.util.typeinference.solver.InferenceResult) TUConstraint(org.checkerframework.framework.util.typeinference.constraint.TUConstraint)

Example 3 with TUConstraint

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);
}
Also used : LinkedHashSet(java.util.LinkedHashSet) F2A(org.checkerframework.framework.util.typeinference.constraint.F2A) TypeVariable(javax.lang.model.type.TypeVariable) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) A2F(org.checkerframework.framework.util.typeinference.constraint.A2F) TUConstraint(org.checkerframework.framework.util.typeinference.constraint.TUConstraint) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) AFConstraint(org.checkerframework.framework.util.typeinference.constraint.AFConstraint) ArrayDeque(java.util.ArrayDeque)

Example 4 with TUConstraint

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);
}
Also used : FIsA(org.checkerframework.framework.util.typeinference.constraint.FIsA) ConstraintMap(org.checkerframework.framework.util.typeinference.solver.ConstraintMap) TUConstraint(org.checkerframework.framework.util.typeinference.constraint.TUConstraint)

Example 5 with TUConstraint

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;
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) TypeVariable(javax.lang.model.type.TypeVariable) QualifierHierarchy(org.checkerframework.framework.type.QualifierHierarchy) AnnotationMirrorSet(org.checkerframework.framework.util.AnnotationMirrorSet) TUConstraint(org.checkerframework.framework.util.typeinference.constraint.TUConstraint) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Aggregations

TUConstraint (org.checkerframework.framework.util.typeinference.constraint.TUConstraint)5 TypeVariable (javax.lang.model.type.TypeVariable)4 AnnotatedTypeVariable (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable)4 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)2 AFConstraint (org.checkerframework.framework.util.typeinference.constraint.AFConstraint)2 ConstraintMap (org.checkerframework.framework.util.typeinference.solver.ConstraintMap)2 ArrayDeque (java.util.ArrayDeque)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 LinkedHashMap (java.util.LinkedHashMap)1 LinkedHashSet (java.util.LinkedHashSet)1 AnnotationMirror (javax.lang.model.element.AnnotationMirror)1 Types (javax.lang.model.util.Types)1 QualifierHierarchy (org.checkerframework.framework.type.QualifierHierarchy)1 AnnotatedTypes (org.checkerframework.framework.util.AnnotatedTypes)1 AnnotationMirrorSet (org.checkerframework.framework.util.AnnotationMirrorSet)1 A2F (org.checkerframework.framework.util.typeinference.constraint.A2F)1 F2A (org.checkerframework.framework.util.typeinference.constraint.F2A)1 FIsA (org.checkerframework.framework.util.typeinference.constraint.FIsA)1 TSubU (org.checkerframework.framework.util.typeinference.constraint.TSubU)1