Search in sources :

Example 26 with BugInCF

use of org.checkerframework.javacutil.BugInCF in project checker-framework by typetools.

the class DefaultTypeArgumentInference method createArgumentAFConstraints.

/**
 * Step 1: Create a constraint {@code Ai << Fi} for each Argument(Ai) to formal parameter(Fi).
 * Remove any constraint that does not involve a type parameter to be inferred. Reduce the
 * remaining constraints so that Fi = Tj where Tj is a type parameter with an argument to be
 * inferred. Return the resulting constraint set.
 *
 * @param typeFactory AnnotatedTypeFactory
 * @param argTypes list of annotated types corresponding to the arguments to the method
 * @param methodType annotated type of the method
 * @param targets type variables to be inferred
 * @param useNullArguments whether or not null method arguments should be considered
 * @return a set of argument constraints
 */
protected Set<AFConstraint> createArgumentAFConstraints(final AnnotatedTypeFactory typeFactory, final List<AnnotatedTypeMirror> argTypes, final AnnotatedExecutableType methodType, final Set<TypeVariable> targets, boolean useNullArguments) {
    final List<AnnotatedTypeMirror> paramTypes = AnnotatedTypes.expandVarArgsParametersFromTypes(methodType, argTypes);
    if (argTypes.size() != paramTypes.size()) {
        throw new BugInCF(StringsPlume.joinLines("Mismatch between formal parameter count and argument count.", "paramTypes=" + StringsPlume.join(",", paramTypes), "argTypes=" + StringsPlume.join(",", argTypes)));
    }
    final int numberOfParams = paramTypes.size();
    final ArrayDeque<AFConstraint> afConstraints = new ArrayDeque<>(numberOfParams);
    for (int i = 0; i < numberOfParams; i++) {
        if (!useNullArguments && argTypes.get(i).getKind() == TypeKind.NULL) {
            continue;
        }
        afConstraints.add(new A2F(argTypes.get(i), paramTypes.get(i)));
    }
    final Set<AFConstraint> reducedConstraints = new LinkedHashSet<>();
    reduceAfConstraints(typeFactory, reducedConstraints, afConstraints, targets);
    return reducedConstraints;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) A2F(org.checkerframework.framework.util.typeinference.constraint.A2F) BugInCF(org.checkerframework.javacutil.BugInCF) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) AFConstraint(org.checkerframework.framework.util.typeinference.constraint.AFConstraint) TUConstraint(org.checkerframework.framework.util.typeinference.constraint.TUConstraint) AFConstraint(org.checkerframework.framework.util.typeinference.constraint.AFConstraint) ArrayDeque(java.util.ArrayDeque)

Example 27 with BugInCF

use of org.checkerframework.javacutil.BugInCF in project checker-framework by typetools.

the class TypeArgInferenceUtil method getArgumentTypes.

/**
 * Returns a list of boxed annotated types corresponding to the arguments in {@code
 * methodInvocation}.
 *
 * @param methodInvocation {@link MethodInvocationTree} or {@link NewClassTree}
 * @param typeFactory type factory
 * @return a list of boxed annotated types corresponding to the arguments in {@code
 *     methodInvocation}.
 */
public static List<AnnotatedTypeMirror> getArgumentTypes(final ExpressionTree methodInvocation, final AnnotatedTypeFactory typeFactory) {
    final List<? extends ExpressionTree> argTrees;
    if (methodInvocation.getKind() == Tree.Kind.METHOD_INVOCATION) {
        argTrees = ((MethodInvocationTree) methodInvocation).getArguments();
    } else if (methodInvocation.getKind() == Tree.Kind.NEW_CLASS) {
        argTrees = ((NewClassTree) methodInvocation).getArguments();
    } else {
        throw new BugInCF("TypeArgumentInference.relationsFromMethodArguments:%n" + "couldn't determine arguments from tree: %s", methodInvocation);
    }
    List<AnnotatedTypeMirror> argTypes = CollectionsPlume.mapList((Tree arg) -> {
        AnnotatedTypeMirror argType = typeFactory.getAnnotatedType(arg);
        if (TypesUtils.isPrimitive(argType.getUnderlyingType())) {
            return typeFactory.getBoxedType((AnnotatedPrimitiveType) argType);
        } else {
            return argType;
        }
    }, argTrees);
    return argTypes;
}
Also used : CompoundAssignmentTree(com.sun.source.tree.CompoundAssignmentTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) AssignmentTree(com.sun.source.tree.AssignmentTree) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) NewArrayTree(com.sun.source.tree.NewArrayTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ReturnTree(com.sun.source.tree.ReturnTree) MethodTree(com.sun.source.tree.MethodTree) VariableTree(com.sun.source.tree.VariableTree) NewClassTree(com.sun.source.tree.NewClassTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) NewClassTree(com.sun.source.tree.NewClassTree) BugInCF(org.checkerframework.javacutil.BugInCF) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 28 with BugInCF

use of org.checkerframework.javacutil.BugInCF 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 29 with BugInCF

use of org.checkerframework.javacutil.BugInCF in project checker-framework by typetools.

the class AnalysisResult method getStoreBefore.

/**
 * Returns the regular store immediately before a given {@link Block}.
 *
 * @param block a block
 * @return the store right before the given block
 */
public S getStoreBefore(Block block) {
    TransferInput<V, S> transferInput = stores.get(block);
    assert transferInput != null : "@AssumeAssertion(nullness): transferInput should be non-null";
    Analysis<V, S, ?> analysis = transferInput.analysis;
    switch(analysis.getDirection()) {
        case FORWARD:
            return transferInput.getRegularStore();
        case BACKWARD:
            Node firstNode;
            switch(block.getType()) {
                case REGULAR_BLOCK:
                    firstNode = block.getNodes().get(0);
                    break;
                case EXCEPTION_BLOCK:
                    firstNode = ((ExceptionBlock) block).getNode();
                    break;
                default:
                    firstNode = null;
            }
            if (firstNode == null) {
                // This block doesn't contains any node, return the store in the transfer input
                return transferInput.getRegularStore();
            }
            return analysis.runAnalysisFor(firstNode, Analysis.BeforeOrAfter.BEFORE, transferInput, nodeValues, analysisCaches);
        default:
            throw new BugInCF("Unknown direction: " + analysis.getDirection());
    }
}
Also used : AssignmentNode(org.checkerframework.dataflow.cfg.node.AssignmentNode) Node(org.checkerframework.dataflow.cfg.node.Node) BugInCF(org.checkerframework.javacutil.BugInCF)

Example 30 with BugInCF

use of org.checkerframework.javacutil.BugInCF in project checker-framework by typetools.

the class BackwardAnalysisImpl method runAnalysisFor.

@Override
public S runAnalysisFor(@FindDistinct Node node, Analysis.BeforeOrAfter preOrPost, TransferInput<V, S> blockTransferInput, IdentityHashMap<Node, V> nodeValues, Map<TransferInput<V, S>, IdentityHashMap<Node, TransferResult<V, S>>> analysisCaches) {
    Block block = node.getBlock();
    assert block != null : "@AssumeAssertion(nullness): invariant";
    Node oldCurrentNode = currentNode;
    if (isRunning) {
        assert currentInput != null : "@AssumeAssertion(nullness): invariant";
        return currentInput.getRegularStore();
    }
    isRunning = true;
    try {
        switch(block.getType()) {
            case REGULAR_BLOCK:
                {
                    RegularBlock rBlock = (RegularBlock) block;
                    // Apply transfer function to contents until we found the node we are looking for.
                    TransferInput<V, S> store = blockTransferInput;
                    List<Node> nodeList = rBlock.getNodes();
                    ListIterator<Node> reverseIter = nodeList.listIterator(nodeList.size());
                    while (reverseIter.hasPrevious()) {
                        Node n = reverseIter.previous();
                        setCurrentNode(n);
                        if (n == node && preOrPost == Analysis.BeforeOrAfter.AFTER) {
                            return store.getRegularStore();
                        }
                        // Copy the store to avoid changing other blocks' transfer inputs in
                        // {@link #inputs}
                        TransferResult<V, S> transferResult = callTransferFunction(n, store.copy());
                        if (n == node) {
                            return transferResult.getRegularStore();
                        }
                        store = new TransferInput<>(n, this, transferResult);
                    }
                    throw new BugInCF("node %s is not in node.getBlock()=%s", node, block);
                }
            case EXCEPTION_BLOCK:
                {
                    ExceptionBlock eb = (ExceptionBlock) block;
                    if (eb.getNode() != node) {
                        throw new BugInCF("Node should be equal to eb.getNode(). But get: node: " + node + "\teb.getNode(): " + eb.getNode());
                    }
                    if (preOrPost == Analysis.BeforeOrAfter.AFTER) {
                        return blockTransferInput.getRegularStore();
                    }
                    setCurrentNode(node);
                    // Copy the store to avoid changing other blocks' transfer inputs in {@link #inputs}
                    TransferResult<V, S> transferResult = callTransferFunction(node, blockTransferInput.copy());
                    // Merge transfer result with the exception store of this exceptional block
                    S exceptionStore = exceptionStores.get(eb);
                    return exceptionStore == null ? transferResult.getRegularStore() : transferResult.getRegularStore().leastUpperBound(exceptionStore);
                }
            default:
                // Only regular blocks and exceptional blocks can hold nodes.
                throw new BugInCF("Unexpected block type: " + block.getType());
        }
    } finally {
        setCurrentNode(oldCurrentNode);
        isRunning = false;
    }
}
Also used : ExceptionBlock(org.checkerframework.dataflow.cfg.block.ExceptionBlock) ReturnNode(org.checkerframework.dataflow.cfg.node.ReturnNode) Node(org.checkerframework.dataflow.cfg.node.Node) RegularBlock(org.checkerframework.dataflow.cfg.block.RegularBlock) ExceptionBlock(org.checkerframework.dataflow.cfg.block.ExceptionBlock) SpecialBlock(org.checkerframework.dataflow.cfg.block.SpecialBlock) Block(org.checkerframework.dataflow.cfg.block.Block) ConditionalBlock(org.checkerframework.dataflow.cfg.block.ConditionalBlock) List(java.util.List) RegularBlock(org.checkerframework.dataflow.cfg.block.RegularBlock) ListIterator(java.util.ListIterator) BugInCF(org.checkerframework.javacutil.BugInCF)

Aggregations

BugInCF (org.checkerframework.javacutil.BugInCF)127 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)29 ArrayList (java.util.ArrayList)28 AnnotationMirror (javax.lang.model.element.AnnotationMirror)26 TypeElement (javax.lang.model.element.TypeElement)26 TypeMirror (javax.lang.model.type.TypeMirror)25 ExecutableElement (javax.lang.model.element.ExecutableElement)24 MethodTree (com.sun.source.tree.MethodTree)20 ExpressionTree (com.sun.source.tree.ExpressionTree)18 VariableTree (com.sun.source.tree.VariableTree)18 Element (javax.lang.model.element.Element)18 ClassTree (com.sun.source.tree.ClassTree)17 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)17 NewClassTree (com.sun.source.tree.NewClassTree)17 LambdaExpressionTree (com.sun.source.tree.LambdaExpressionTree)16 IOException (java.io.IOException)16 Tree (com.sun.source.tree.Tree)15 Map (java.util.Map)15 List (java.util.List)14 VariableElement (javax.lang.model.element.VariableElement)14