Search in sources :

Example 1 with InferredType

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

the class DefaultTypeArgumentInference method combineSupertypeAndAssignmentResults.

/**
 * Step 4. Combine the results from using the Supertype constraints the Equality constraints from
 * the assignment context.
 */
private InferenceResult combineSupertypeAndAssignmentResults(Set<TypeVariable> targets, AnnotatedTypeFactory typeFactory, InferenceResult equalityResult, InferenceResult supertypeResult) {
    final TypeHierarchy typeHierarchy = typeFactory.getTypeHierarchy();
    final InferenceResult result = new InferenceResult();
    for (final TypeVariable target : targets) {
        final InferredValue equalityInferred = equalityResult.get(target);
        final InferredValue supertypeInferred = supertypeResult.get(target);
        final InferredValue outputValue;
        if (equalityInferred instanceof InferredType) {
            if (supertypeInferred instanceof InferredType) {
                AnnotatedTypeMirror superATM = ((InferredType) supertypeInferred).type;
                AnnotatedTypeMirror equalityATM = ((InferredType) equalityInferred).type;
                if (TypesUtils.isErasedSubtype(equalityATM.getUnderlyingType(), superATM.getUnderlyingType(), typeFactory.getChecker().getTypeUtils())) {
                    // If the underlying type of equalityATM is a subtype of the underlying
                    // type of superATM, then the call to isSubtype below will issue an error.
                    // So call asSuper so that the isSubtype call below works correctly.
                    equalityATM = AnnotatedTypes.asSuper(typeFactory, equalityATM, superATM);
                }
                if (typeHierarchy.isSubtype(superATM, equalityATM)) {
                    outputValue = equalityInferred;
                } else {
                    outputValue = supertypeInferred;
                }
            } else {
                outputValue = equalityInferred;
            }
        } else {
            if (supertypeInferred != null) {
                outputValue = supertypeInferred;
            } else {
                outputValue = null;
            }
        }
        if (outputValue != null) {
            result.put(target, outputValue);
        }
    }
    return result;
}
Also used : InferredValue(org.checkerframework.framework.util.typeinference.solver.InferredValue) InferredType(org.checkerframework.framework.util.typeinference.solver.InferredValue.InferredType) TypeVariable(javax.lang.model.type.TypeVariable) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) InferenceResult(org.checkerframework.framework.util.typeinference.solver.InferenceResult) TypeHierarchy(org.checkerframework.framework.type.TypeHierarchy) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 2 with InferredType

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

the class EqualitiesSolver method mergeConstraints.

public InferredValue mergeConstraints(final TypeVariable target, final Equalities equalities, final InferenceResult solution, ConstraintMap constraintMap, AnnotatedTypeFactory typeFactory) {
    final AnnotationMirrorSet tops = new AnnotationMirrorSet(typeFactory.getQualifierHierarchy().getTopAnnotations());
    InferredValue inferred = null;
    if (!equalities.types.isEmpty()) {
        inferred = mergeTypesAndPrimaries(equalities.types, equalities.primaries, tops, typeFactory);
    }
    if (inferred != null) {
        return inferred;
    }
    // else
    // We did not have enough information to infer an annotation in all hierarchies for one
    // concrete type.
    // However, we have a "partial solution", one in which we know the type in some but not all
    // qualifier hierarchies.
    // Update our set of constraints with this information
    dirty |= updateTargetsWithPartiallyInferredType(equalities, constraintMap, typeFactory);
    inferred = findEqualTarget(equalities, tops);
    if (inferred == null && equalities.types.size() == 1) {
        // Still could not find an inferred type in all hierarchies, so just use what type is known.
        AnnotatedTypeMirror type = equalities.types.keySet().iterator().next();
        inferred = new InferredType(type);
    }
    return inferred;
}
Also used : InferredType(org.checkerframework.framework.util.typeinference.solver.InferredValue.InferredType) AnnotationMirrorSet(org.checkerframework.framework.util.AnnotationMirrorSet) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 3 with InferredType

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

the class EqualitiesSolver method solveEqualities.

/**
 * For each target, if there is one or more equality constraints involving concrete types that
 * lets us infer a primary annotation in all qualifier hierarchies then infer a concrete type
 * argument. else if there is one or more equality constraints involving other targets that lets
 * us infer a primary annotation in all qualifier hierarchies then infer that type argument is the
 * other type argument
 *
 * <p>if we have inferred either a concrete type or another target as type argument rewrite all of
 * the constraints for the current target to instead use the inferred type/target
 *
 * <p>We do this iteratively until NO new inferred type argument is found
 *
 * @param targets the list of type parameters for which we are inferring type arguments
 * @param constraintMap the set of constraints over the set of targets
 * @return a Map from target to (inferred type or target)
 */
public InferenceResult solveEqualities(Set<TypeVariable> targets, ConstraintMap constraintMap, AnnotatedTypeFactory typeFactory) {
    final InferenceResult solution = new InferenceResult();
    do {
        dirty = false;
        for (TypeVariable target : targets) {
            if (solution.containsKey(target)) {
                continue;
            }
            Equalities equalities = constraintMap.getConstraints(target).equalities;
            InferredValue inferred = mergeConstraints(target, equalities, solution, constraintMap, typeFactory);
            if (inferred != null) {
                if (inferred instanceof InferredType) {
                    rewriteWithInferredType(target, ((InferredType) inferred).type, constraintMap);
                } else {
                    rewriteWithInferredTarget(target, ((InferredTarget) inferred).target, constraintMap, typeFactory);
                }
                solution.put(target, inferred);
            }
        }
    } while (dirty);
    solution.resolveChainedTargets();
    return solution;
}
Also used : InferredType(org.checkerframework.framework.util.typeinference.solver.InferredValue.InferredType) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable) TypeVariable(javax.lang.model.type.TypeVariable) Equalities(org.checkerframework.framework.util.typeinference.solver.TargetConstraints.Equalities)

Example 4 with InferredType

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

the class EqualitiesSolver method mergeTypesAndPrimaries.

/**
 * Returns a concrete type argument or null if there was not enough information to infer one.
 *
 * @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, AnnotatedTypeFactory typeFactory) {
    final AnnotationMirrorSet missingAnnos = new AnnotationMirrorSet(tops);
    Iterator<Map.Entry<AnnotatedTypeMirror, AnnotationMirrorSet>> entryIterator = typesToHierarchies.entrySet().iterator();
    if (!entryIterator.hasNext()) {
        throw new BugInCF("Merging a list of empty types.");
    }
    final Map.Entry<AnnotatedTypeMirror, AnnotationMirrorSet> head = entryIterator.next();
    AnnotatedTypeMirror mergedType = head.getKey();
    missingAnnos.removeAll(head.getValue());
    // AnnotatedDeclaredTypes, AnnotatedTypeVariables, and AnnotatedArrayTypes
    while (entryIterator.hasNext() && !missingAnnos.isEmpty()) {
        final Map.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 && typeFactory.types.isSameType(currentType.getUnderlyingType(), 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
                    throw new BugInCF("Missing annotation.%nmergedType=%s%ncurrentType=%s", mergedType, currentType);
                }
            }
        }
        missingAnnos.removeAll(found);
    }
    // add all the annotations from the primaries
    for (final AnnotationMirror top : missingAnnos) {
        final AnnotationMirror anno = primaries.get(top);
        if (anno != null) {
            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) InferredType(org.checkerframework.framework.util.typeinference.solver.InferredValue.InferredType) AnnotationMirrorSet(org.checkerframework.framework.util.AnnotationMirrorSet) BugInCF(org.checkerframework.javacutil.BugInCF) AnnotationMirrorMap(org.checkerframework.framework.util.AnnotationMirrorMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 5 with InferredType

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

the class InferenceResult method resolveChainedTargets.

/**
 * If we had a set of inferred results, (e.g. T1 = T2, T2 = T3, T3 = String) propagate any results
 * we have (the above constraints become T1 = String, T2 = String, T3 = String)
 */
public void resolveChainedTargets() {
    final Map<TypeVariable, InferredValue> inferredTypes = new LinkedHashMap<>(this.size());
    // TODO: we can probably make this a bit more efficient
    boolean grew = true;
    while (grew) {
        grew = false;
        for (final Map.Entry<TypeVariable, InferredValue> inferred : this.entrySet()) {
            final TypeVariable target = inferred.getKey();
            final InferredValue value = inferred.getValue();
            if (value instanceof InferredType) {
                inferredTypes.put(target, value);
            } else {
                final InferredTarget currentTarget = (InferredTarget) value;
                final InferredType equivalentType = (InferredType) inferredTypes.get(((InferredTarget) value).target);
                if (equivalentType != null) {
                    grew = true;
                    final AnnotatedTypeMirror type = equivalentType.type.deepCopy();
                    type.replaceAnnotations(currentTarget.additionalAnnotations);
                    final InferredType newConstraint = new InferredType(type);
                    inferredTypes.put(currentTarget.target, newConstraint);
                }
            }
        }
    }
    this.putAll(inferredTypes);
}
Also used : InferredTarget(org.checkerframework.framework.util.typeinference.solver.InferredValue.InferredTarget) InferredType(org.checkerframework.framework.util.typeinference.solver.InferredValue.InferredType) TypeVariable(javax.lang.model.type.TypeVariable) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) LinkedHashMap(java.util.LinkedHashMap)

Aggregations

InferredType (org.checkerframework.framework.util.typeinference.solver.InferredValue.InferredType)12 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)11 AnnotationMirrorSet (org.checkerframework.framework.util.AnnotationMirrorSet)8 Map (java.util.Map)6 AnnotationMirror (javax.lang.model.element.AnnotationMirror)6 TypeVariable (javax.lang.model.type.TypeVariable)5 AnnotationMirrorMap (org.checkerframework.framework.util.AnnotationMirrorMap)5 LinkedHashMap (java.util.LinkedHashMap)4 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 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 BugInCF (org.checkerframework.javacutil.BugInCF)1