use of org.checkerframework.framework.type.AnnotatedTypeParameterBounds in project checker-framework by typetools.
the class DependentTypesHelper method viewpointAdaptTypeVariableBounds.
/**
* Viewpoint-adapts the dependent type annotations on the bounds to the use of the type.
*
* @param classDecl class or interface declaration whose type variables should be viewpoint
* adapted
* @param bounds annotated types of the bounds of the type variables
* @param pathToUse tree path to the use of the class or interface
*/
public void viewpointAdaptTypeVariableBounds(TypeElement classDecl, List<AnnotatedTypeParameterBounds> bounds, TreePath pathToUse) {
FlowExpressions.Receiver r = FlowExpressions.internalReprOfImplicitReceiver(classDecl);
FlowExpressionContext context = new FlowExpressionContext(r, null, factory.getContext());
for (AnnotatedTypeParameterBounds bound : bounds) {
standardizeDoNotUseLocals(context, pathToUse, bound.getUpperBound());
standardizeDoNotUseLocals(context, pathToUse, bound.getLowerBound());
}
}
use of org.checkerframework.framework.type.AnnotatedTypeParameterBounds in project checker-framework by typetools.
the class BaseTypeValidator method visitParameterizedType.
/**
* Checks that the annotations on the type arguments supplied to a type or a method invocation
* are within the bounds of the type variables as declared, and issues the
* "type.argument.type.incompatible" error if they are not.
*
* <p>This method used to be visitParameterizedType, which incorrectly handles the main
* annotation on generic types.
*/
protected Void visitParameterizedType(AnnotatedDeclaredType type, ParameterizedTypeTree tree) {
if (TreeUtils.isDiamondTree(tree)) {
return null;
}
final TypeElement element = (TypeElement) type.getUnderlyingType().asElement();
if (checker.shouldSkipUses(element)) {
return null;
}
List<AnnotatedTypeParameterBounds> bounds = atypeFactory.typeVariablesFromUse(type, element);
visitor.checkTypeArguments(tree, bounds, type.getTypeArguments(), tree.getTypeArguments());
return null;
}
use of org.checkerframework.framework.type.AnnotatedTypeParameterBounds in project checker-framework by typetools.
the class BaseTypeVisitor method visitMethodInvocation.
/**
* Performs a method invocation check.
*
* <p>An invocation of a method, m, on the receiver, r is valid only if:
*
* <ul>
* <li>passed arguments are subtypes of corresponding m parameters
* <li>r is a subtype of m receiver type
* <li>if m is generic, passed type arguments are subtypes of m type variables
* </ul>
*/
@Override
public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
// hard to check), also see CFGBuilder.visitMethodInvocation.
if (TreeUtils.elementFromUse(node) == null || TreeUtils.isEnumSuper(node)) {
return super.visitMethodInvocation(node, p);
}
if (shouldSkipUses(node)) {
return super.visitMethodInvocation(node, p);
}
Pair<AnnotatedExecutableType, List<AnnotatedTypeMirror>> mfuPair = atypeFactory.methodFromUse(node);
AnnotatedExecutableType invokedMethod = mfuPair.first;
List<AnnotatedTypeMirror> typeargs = mfuPair.second;
if (!atypeFactory.ignoreUninferredTypeArguments) {
for (AnnotatedTypeMirror typearg : typeargs) {
if (typearg.getKind() == TypeKind.WILDCARD && ((AnnotatedWildcardType) typearg).isUninferredTypeArgument()) {
checker.report(Result.failure("type.arguments.not.inferred", invokedMethod.getElement().getSimpleName()), node);
// only issue error once per method
break;
}
}
}
List<AnnotatedTypeParameterBounds> paramBounds = new ArrayList<>();
for (AnnotatedTypeVariable param : invokedMethod.getTypeVariables()) {
paramBounds.add(param.getBounds());
}
checkTypeArguments(node, paramBounds, typeargs, node.getTypeArguments());
List<AnnotatedTypeMirror> params = AnnotatedTypes.expandVarArgs(atypeFactory, invokedMethod, node.getArguments());
checkArguments(params, node.getArguments());
checkVarargs(invokedMethod, node);
if (isVectorCopyInto(invokedMethod)) {
typeCheckVectorCopyIntoArgument(node, params);
}
ExecutableElement invokedMethodElement = invokedMethod.getElement();
if (!ElementUtils.isStatic(invokedMethodElement) && !TreeUtils.isSuperCall(node)) {
checkMethodInvocability(invokedMethod, node);
}
// check precondition annotations
checkPreconditions(node, contractsUtils.getPreconditions(invokedMethodElement));
// Do not call super, as that would observe the arguments without
// a set assignment context.
scan(node.getMethodSelect(), p);
// super.visitMethodInvocation(node, p);
return null;
}
use of org.checkerframework.framework.type.AnnotatedTypeParameterBounds in project checker-framework by typetools.
the class BaseTypeVisitor method visitNewClass.
/**
* Performs a new class invocation check.
*
* <p>An invocation of a constructor, c, is valid only if:
*
* <ul>
* <li>passed arguments are subtypes of corresponding c parameters
* <li>if c is generic, passed type arguments are subtypes of c type variables
* </ul>
*/
@Override
public Void visitNewClass(NewClassTree node, Void p) {
if (checker.shouldSkipUses(TreeUtils.constructor(node))) {
return super.visitNewClass(node, p);
}
Pair<AnnotatedExecutableType, List<AnnotatedTypeMirror>> fromUse = atypeFactory.constructorFromUse(node);
AnnotatedExecutableType constructor = fromUse.first;
List<AnnotatedTypeMirror> typeargs = fromUse.second;
List<? extends ExpressionTree> passedArguments = node.getArguments();
List<AnnotatedTypeMirror> params = AnnotatedTypes.expandVarArgs(atypeFactory, constructor, passedArguments);
checkArguments(params, passedArguments);
checkVarargs(constructor, node);
List<AnnotatedTypeParameterBounds> paramBounds = new ArrayList<>();
for (AnnotatedTypeVariable param : constructor.getTypeVariables()) {
paramBounds.add(param.getBounds());
}
checkTypeArguments(node, paramBounds, typeargs, node.getTypeArguments());
boolean valid = validateTypeOf(node);
if (valid) {
AnnotatedDeclaredType dt = atypeFactory.getAnnotatedType(node);
if (atypeFactory.getDependentTypesHelper() != null) {
atypeFactory.getDependentTypesHelper().checkType(dt, node);
}
checkConstructorInvocation(dt, constructor, node);
}
// Do not call super, as that would observe the arguments without
// a set assignment context.
scan(node.getEnclosingExpression(), p);
scan(node.getIdentifier(), p);
scan(node.getClassBody(), p);
return null;
}
use of org.checkerframework.framework.type.AnnotatedTypeParameterBounds in project checker-framework by typetools.
the class BaseTypeVisitor method checkTypeArguments.
/**
* Checks that the annotations on the type arguments supplied to a type or a method invocation
* are within the bounds of the type variables as declared, and issues the
* "type.argument.type.incompatible" error if they are not.
*
* @param toptree the tree for error reporting, only used for inferred type arguments
* @param paramBounds the bounds of the type parameters from a class or method declaration
* @param typeargs the type arguments from the type or method invocation
* @param typeargTrees the type arguments as trees, used for error reporting
*/
// TODO: see updated version below that performs more well-formedness checks.
protected void checkTypeArguments(Tree toptree, List<? extends AnnotatedTypeParameterBounds> paramBounds, List<? extends AnnotatedTypeMirror> typeargs, List<? extends Tree> typeargTrees) {
// If there are no type variables, do nothing.
if (paramBounds.isEmpty()) {
return;
}
assert paramBounds.size() == typeargs.size() : "BaseTypeVisitor.checkTypeArguments: mismatch between type arguments: " + typeargs + " and type parameter bounds" + paramBounds;
Iterator<? extends AnnotatedTypeParameterBounds> boundsIter = paramBounds.iterator();
Iterator<? extends AnnotatedTypeMirror> argIter = typeargs.iterator();
while (boundsIter.hasNext()) {
AnnotatedTypeParameterBounds bounds = boundsIter.next();
AnnotatedTypeMirror typeArg = argIter.next();
if (isIgnoredUninferredWildcard(bounds.getUpperBound()) || isIgnoredUninferredWildcard(typeArg)) {
continue;
}
if (shouldBeCaptureConverted(typeArg, bounds)) {
continue;
}
AnnotatedTypeMirror paramUpperBound = bounds.getUpperBound();
if (typeArg.getKind() == TypeKind.WILDCARD) {
paramUpperBound = atypeFactory.widenToUpperBound(paramUpperBound, (AnnotatedWildcardType) typeArg);
}
if (typeargTrees == null || typeargTrees.isEmpty()) {
// The type arguments were inferred and we mark the whole method.
// The inference fails if we provide invalid arguments,
// therefore issue an error for the arguments.
// I hope this is less confusing for users.
commonAssignmentCheck(paramUpperBound, typeArg, toptree, "type.argument.type.incompatible");
} else {
commonAssignmentCheck(paramUpperBound, typeArg, typeargTrees.get(typeargs.indexOf(typeArg)), "type.argument.type.incompatible");
}
if (!atypeFactory.getTypeHierarchy().isSubtype(bounds.getLowerBound(), typeArg)) {
if (typeargTrees == null || typeargTrees.isEmpty()) {
// The type arguments were inferred and we mark the whole method.
checker.report(Result.failure("type.argument.type.incompatible", typeArg, bounds), toptree);
} else {
checker.report(Result.failure("type.argument.type.incompatible", typeArg, bounds), typeargTrees.get(typeargs.indexOf(typeArg)));
}
}
}
}
Aggregations