Search in sources :

Example 36 with AnnotatedTypeVariable

use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable 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 37 with AnnotatedTypeVariable

use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable 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);
                }
            }
        }
    }
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) InferredValue(org.checkerframework.framework.util.typeinference.solver.InferredValue) InferredType(org.checkerframework.framework.util.typeinference.solver.InferredValue.InferredType) QualifierHierarchy(org.checkerframework.framework.type.QualifierHierarchy) AnnotationMirrorSet(org.checkerframework.framework.util.AnnotationMirrorSet) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 38 with AnnotatedTypeVariable

use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable 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;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) TypeVariable(javax.lang.model.type.TypeVariable) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable)

Example 39 with AnnotatedTypeVariable

use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable 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;
}
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)

Example 40 with AnnotatedTypeVariable

use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable in project checker-framework by typetools.

the class SupertypesSolver method leastUpperBound.

/**
 * Successively calls least upper bound on the elements of types. Unlike
 * AnnotatedTypes.leastUpperBound, this method will box primitives if necessary
 */
public static AnnotatedTypeMirror leastUpperBound(final TypeVariable target, final AnnotatedTypeFactory typeFactory, final Map<AnnotatedTypeMirror, AnnotationMirrorSet> types) {
    QualifierHierarchy qualifierHierarchy = typeFactory.getQualifierHierarchy();
    AnnotatedTypeVariable targetsDeclaredType = (AnnotatedTypeVariable) typeFactory.getAnnotatedType(target.asElement());
    final AnnotationMirrorMap<AnnotationMirror> lowerBoundAnnos = TypeArgInferenceUtil.createHierarchyMap(new AnnotationMirrorSet(targetsDeclaredType.getLowerBound().getEffectiveAnnotations()), qualifierHierarchy);
    final Iterator<Entry<AnnotatedTypeMirror, AnnotationMirrorSet>> typesIter = types.entrySet().iterator();
    if (!typesIter.hasNext()) {
        ErrorReporter.errorAbort("Calling LUB on empty list!");
    }
    /**
     * If a constraint implies that a type parameter Ti is a supertype of an annotated type
     * mirror Ai but only in a subset of all qualifier hierarchies then for all other qualifier
     * hierarchies replace the primary annotation on Ai with the lowest possible annotation
     * (ensuring that it won't be the LUB unless there are no other constraints, or all other
     * constraints imply the bottom annotation is the LUB). Note: Even if we choose bottom as
     * the lub here, the assignment context may raise this annotation.
     */
    final Entry<AnnotatedTypeMirror, AnnotationMirrorSet> head = typesIter.next();
    AnnotatedTypeMirror lubType = groundMissingHierarchies(head, lowerBoundAnnos);
    AnnotatedTypeMirror nextType = null;
    while (typesIter.hasNext()) {
        nextType = groundMissingHierarchies(typesIter.next(), lowerBoundAnnos);
        if (lubType.getKind().isPrimitive()) {
            if (!nextType.getKind().isPrimitive()) {
                lubType = typeFactory.getBoxedType((AnnotatedPrimitiveType) lubType);
            }
        } else if (nextType.getKind().isPrimitive()) {
            if (!lubType.getKind().isPrimitive()) {
                nextType = typeFactory.getBoxedType((AnnotatedPrimitiveType) nextType);
            }
        }
        lubType = AnnotatedTypes.leastUpperBound(typeFactory, lubType, nextType);
    }
    return lubType;
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) Entry(java.util.Map.Entry) QualifierHierarchy(org.checkerframework.framework.type.QualifierHierarchy) AnnotationMirrorSet(org.checkerframework.framework.util.AnnotationMirrorSet) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) AnnotatedPrimitiveType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedPrimitiveType)

Aggregations

AnnotatedTypeVariable (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable)40 TypeVariable (javax.lang.model.type.TypeVariable)16 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)16 ArrayList (java.util.ArrayList)13 AnnotationMirror (javax.lang.model.element.AnnotationMirror)9 AnnotatedDeclaredType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType)9 AnnotatedWildcardType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedWildcardType)7 AnnotatedExecutableType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType)5 HashMap (java.util.HashMap)4 LinkedHashMap (java.util.LinkedHashMap)3 ExecutableElement (javax.lang.model.element.ExecutableElement)3 TypeElement (javax.lang.model.element.TypeElement)3 QualifierHierarchy (org.checkerframework.framework.type.QualifierHierarchy)3 AnnotationMirrorSet (org.checkerframework.framework.util.AnnotationMirrorSet)3 TUConstraint (org.checkerframework.framework.util.typeinference.constraint.TUConstraint)3 TypeParameter (com.github.javaparser.ast.type.TypeParameter)2 ClassTree (com.sun.source.tree.ClassTree)2 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)2 MethodTree (com.sun.source.tree.MethodTree)2 TypeParameterTree (com.sun.source.tree.TypeParameterTree)2