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;
}
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;
}
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 → hierarchies) that indicate that the
* argument being inferred is equal to the types in each of the hierarchies
* @param primaries a map (hierarchy → 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;
}
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());
}
}
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;
}
}
Aggregations