Search in sources :

Example 6 with InferredType

use of org.checkerframework.framework.util.typeinference.solver.InferredValue.InferredType in project checker-framework by typetools.

the class SubtypesSolver method propagatePreviousGlbs.

/**
 * /** If the target corresponding to targetRecord must be a subtype of another target for which
 * we have already determined a GLB, add that target's GLB to the list of subtypes to be GLBed
 * for this target.
 */
protected static void propagatePreviousGlbs(final Subtypes targetSubtypes, InferenceResult solution, final Map<AnnotatedTypeMirror, AnnotationMirrorSet> subtypesOfTarget) {
    for (final Entry<TypeVariable, AnnotationMirrorSet> subtypeTarget : targetSubtypes.targets.entrySet()) {
        final InferredValue subtargetInferredGlb = solution.get(subtypeTarget.getKey());
        if (subtargetInferredGlb != null) {
            final AnnotatedTypeMirror subtargetGlbType = ((InferredType) subtargetInferredGlb).type;
            AnnotationMirrorSet subtargetAnnos = subtypesOfTarget.get(subtargetGlbType);
            if (subtargetAnnos != null) {
                // there is already an equivalent type in the list of subtypes, just add
                // any hierarchies that are not in its list but are in the supertarget's list
                subtargetAnnos.addAll(subtypeTarget.getValue());
            } else {
                subtypesOfTarget.put(subtargetGlbType, subtypeTarget.getValue());
            }
        }
    }
}
Also used : InferredType(org.checkerframework.framework.util.typeinference.solver.InferredValue.InferredType) TypeVariable(javax.lang.model.type.TypeVariable) AnnotationMirrorSet(org.checkerframework.framework.util.AnnotationMirrorSet) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 7 with InferredType

use of org.checkerframework.framework.util.typeinference.solver.InferredValue.InferredType in project checker-framework by typetools.

the class SubtypesSolver method glbSubtypes.

public InferenceResult glbSubtypes(final Set<TypeVariable> remainingTargets, final ConstraintMap constraints, final AnnotatedTypeFactory typeFactory) {
    final InferenceResult inferenceResult = new InferenceResult();
    final QualifierHierarchy qualifierHierarchy = typeFactory.getQualifierHierarchy();
    final Types types = typeFactory.getProcessingEnv().getTypeUtils();
    List<TypeVariable> targetsSubtypesLast = new ArrayList<>(remainingTargets);
    // If we have two type variables <A, A extends B> order them A then B
    // this is required because we will use the fact that B must be below A
    // when determining the glb of B
    Collections.sort(targetsSubtypesLast, 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 : targetsSubtypesLast) {
        Subtypes subtypes = constraints.getConstraints(target).subtypes;
        if (subtypes.types.isEmpty()) {
            continue;
        }
        propagatePreviousGlbs(subtypes, inferenceResult, subtypes.types);
        // if the subtypes size is only 1 then we need not do any GLBing on the underlying types
        // but we may have primary annotations that need to be GLBed
        AnnotationMirrorMap<AnnotationMirrorSet> primaries = subtypes.primaries;
        if (subtypes.types.size() == 1) {
            final Entry<AnnotatedTypeMirror, AnnotationMirrorSet> entry = subtypes.types.entrySet().iterator().next();
            AnnotatedTypeMirror supertype = entry.getKey().deepCopy();
            for (AnnotationMirror top : entry.getValue()) {
                final AnnotationMirrorSet superAnnos = primaries.get(top);
                // if it is null we're just going to use the anno already on supertype
                if (superAnnos != null) {
                    final AnnotationMirror supertypeAnno = supertype.getAnnotationInHierarchy(top);
                    superAnnos.add(supertypeAnno);
                }
            }
            if (!primaries.isEmpty()) {
                for (AnnotationMirror top : qualifierHierarchy.getTopAnnotations()) {
                    final AnnotationMirror glb = greatestLowerBound(subtypes.primaries.get(top), qualifierHierarchy);
                    supertype.replaceAnnotation(glb);
                }
            }
            inferenceResult.put(target, new InferredType(supertype));
        } else {
            // GLB all of the types than combine this with the GLB of primary annotation
            // constraints
            final AnnotatedTypeMirror glbType = GlbUtil.glbAll(subtypes.types, typeFactory);
            if (glbType != null) {
                if (!primaries.isEmpty()) {
                    for (AnnotationMirror top : qualifierHierarchy.getTopAnnotations()) {
                        final AnnotationMirror glb = greatestLowerBound(subtypes.primaries.get(top), qualifierHierarchy);
                        final AnnotationMirror currentAnno = glbType.getAnnotationInHierarchy(top);
                        if (currentAnno == null) {
                            glbType.addAnnotation(glb);
                        } else if (glb != null) {
                            glbType.replaceAnnotation(qualifierHierarchy.greatestLowerBound(glb, currentAnno));
                        }
                    }
                }
                inferenceResult.put(target, new InferredType(glbType));
            }
        }
    }
    return inferenceResult;
}
Also used : Types(javax.lang.model.util.Types) InferredType(org.checkerframework.framework.util.typeinference.solver.InferredValue.InferredType) ArrayList(java.util.ArrayList) Subtypes(org.checkerframework.framework.util.typeinference.solver.TargetConstraints.Subtypes) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) AnnotationMirror(javax.lang.model.element.AnnotationMirror) TypeVariable(javax.lang.model.type.TypeVariable) QualifierHierarchy(org.checkerframework.framework.type.QualifierHierarchy) AnnotationMirrorSet(org.checkerframework.framework.util.AnnotationMirrorSet)

Example 8 with InferredType

use of org.checkerframework.framework.util.typeinference.solver.InferredValue.InferredType 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 9 with InferredType

use of org.checkerframework.framework.util.typeinference.solver.InferredValue.InferredType in project checker-framework by typetools.

the class EqualitiesSolver method mergeTypesAndPrimaries.

/**
 * @param typesToHierarchies a mapping of (types &rarr; hierarchies) that indicate that the
 *     argument being inferred is equal to the types in each of the hierarchies
 * @param primaries a map (hierarchy &rarr; annotation in hierarchy) where the annotation in
 *     hierarchy is equal to the primary annotation on the argument being inferred
 * @param tops the set of top annotations in the qualifier hierarchy
 * @return a concrete type argument or null if there was not enough information to infer one
 */
private InferredType mergeTypesAndPrimaries(Map<AnnotatedTypeMirror, AnnotationMirrorSet> typesToHierarchies, AnnotationMirrorMap<AnnotationMirror> primaries, final AnnotationMirrorSet tops) {
    final AnnotationMirrorSet missingAnnos = new AnnotationMirrorSet(tops);
    Iterator<Entry<AnnotatedTypeMirror, AnnotationMirrorSet>> entryIterator = typesToHierarchies.entrySet().iterator();
    if (!entryIterator.hasNext()) {
        ErrorReporter.errorAbort("Merging a list of empty types!");
    }
    final Entry<AnnotatedTypeMirror, AnnotationMirrorSet> head = entryIterator.next();
    AnnotatedTypeMirror mergedType = head.getKey();
    missingAnnos.removeAll(head.getValue());
    // AnnotatedDeclaredTypes, AnnotatedTypeVariables, and AnnotatedArrayTypes
    while (entryIterator.hasNext() && !missingAnnos.isEmpty()) {
        final Entry<AnnotatedTypeMirror, AnnotationMirrorSet> current = entryIterator.next();
        final AnnotatedTypeMirror currentType = current.getKey();
        final AnnotationMirrorSet currentHierarchies = current.getValue();
        AnnotationMirrorSet found = new AnnotationMirrorSet();
        for (AnnotationMirror top : missingAnnos) {
            if (currentHierarchies.contains(top)) {
                final AnnotationMirror newAnno = currentType.getAnnotationInHierarchy(top);
                if (newAnno != null) {
                    mergedType.replaceAnnotation(newAnno);
                    found.add(top);
                } else if (mergedType.getKind() == TypeKind.TYPEVAR && currentType.getUnderlyingType().equals(mergedType.getUnderlyingType())) {
                    // the options here are we are merging with the same typevar, in which case
                    // we can just remove the annotation from the missing list
                    found.add(top);
                } else {
                    // otherwise the other type is missing an annotation
                    ErrorReporter.errorAbort("Missing annotation.\n" + "\nmergedType=" + mergedType + "\ncurrentType=" + currentType);
                }
            }
        }
        missingAnnos.removeAll(found);
    }
    // add all the annotations from the primaries
    final AnnotationMirrorSet foundHierarchies = new AnnotationMirrorSet();
    for (final AnnotationMirror top : missingAnnos) {
        final AnnotationMirror anno = primaries.get(top);
        if (anno != null) {
            foundHierarchies.add(top);
            mergedType.replaceAnnotation(anno);
        }
    }
    typesToHierarchies.clear();
    if (missingAnnos.isEmpty()) {
        return new InferredType(mergedType);
    }
    // TODO: we probably can do more with this information than just putting it back into the
    // TODO: ConstraintMap (which is what's happening here)
    final AnnotationMirrorSet hierarchies = new AnnotationMirrorSet(tops);
    hierarchies.removeAll(missingAnnos);
    typesToHierarchies.put(mergedType, hierarchies);
    return null;
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) Entry(java.util.Map.Entry) InferredType(org.checkerframework.framework.util.typeinference.solver.InferredValue.InferredType) AnnotationMirrorSet(org.checkerframework.framework.util.AnnotationMirrorSet) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 10 with InferredType

use of org.checkerframework.framework.util.typeinference.solver.InferredValue.InferredType in project checker-framework by typetools.

the class SupertypesSolver method mergeLubTypeWithEqualities.

/**
 * We previously found a type that is equal to target but not in all hierarchies. Use the
 * primary annotations from the lub type to fill in the missing annotations in this type. Use
 * that type as the inferred argument.
 *
 * <p>If we failed to infer any annotation for a given hierarchy, either previously from
 * equalities or from the lub, return null.
 */
protected InferredType mergeLubTypeWithEqualities(final TypeVariable target, final AnnotatedTypeMirror lub, final ConstraintMap constraintMap, final AnnotatedTypeFactory typeFactory) {
    final Equalities equalities = constraintMap.getConstraints(target).equalities;
    final AnnotationMirrorSet tops = new AnnotationMirrorSet(typeFactory.getQualifierHierarchy().getTopAnnotations());
    if (!equalities.types.isEmpty()) {
        // there should be only one equality type if any at this point
        final Entry<AnnotatedTypeMirror, AnnotationMirrorSet> eqEntry = equalities.types.entrySet().iterator().next();
        final AnnotatedTypeMirror equalityType = eqEntry.getKey();
        final AnnotationMirrorSet equalityAnnos = eqEntry.getValue();
        boolean failed = false;
        for (final AnnotationMirror top : tops) {
            if (!equalityAnnos.contains(top)) {
                final AnnotationMirror lubAnno = lub.getAnnotationInHierarchy(top);
                if (lubAnno == null) {
                    // unannotated then "NO ANNOTATION" is the correct choice.
                    if (lub.getKind() == TypeKind.TYPEVAR && equalityType.getUnderlyingType().equals(lub.getUnderlyingType())) {
                        equalityAnnos.add(top);
                    } else {
                        failed = true;
                    }
                } else {
                    equalityType.replaceAnnotation(lubAnno);
                    equalityAnnos.add(top);
                }
            }
        }
        if (!failed) {
            return new InferredType(equalityType);
        }
    }
    return new InferredType(lub);
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) InferredType(org.checkerframework.framework.util.typeinference.solver.InferredValue.InferredType) Equalities(org.checkerframework.framework.util.typeinference.solver.TargetConstraints.Equalities) AnnotationMirrorSet(org.checkerframework.framework.util.AnnotationMirrorSet) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Aggregations

InferredType (org.checkerframework.framework.util.typeinference.solver.InferredValue.InferredType)11 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)10 AnnotationMirrorSet (org.checkerframework.framework.util.AnnotationMirrorSet)7 AnnotationMirror (javax.lang.model.element.AnnotationMirror)5 TypeVariable (javax.lang.model.type.TypeVariable)5 AnnotatedTypeVariable (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable)3 Equalities (org.checkerframework.framework.util.typeinference.solver.TargetConstraints.Equalities)3 QualifierHierarchy (org.checkerframework.framework.type.QualifierHierarchy)2 InferredValue (org.checkerframework.framework.util.typeinference.solver.InferredValue)2 InferredTarget (org.checkerframework.framework.util.typeinference.solver.InferredValue.InferredTarget)2 ArrayList (java.util.ArrayList)1 LinkedHashMap (java.util.LinkedHashMap)1 Entry (java.util.Map.Entry)1 Types (javax.lang.model.util.Types)1 TypeHierarchy (org.checkerframework.framework.type.TypeHierarchy)1 InferenceResult (org.checkerframework.framework.util.typeinference.solver.InferenceResult)1 Subtypes (org.checkerframework.framework.util.typeinference.solver.TargetConstraints.Subtypes)1