Search in sources :

Example 1 with AnnotatedTypeParameterBounds

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());
    }
}
Also used : AnnotatedTypeParameterBounds(org.checkerframework.framework.type.AnnotatedTypeParameterBounds) FlowExpressionContext(org.checkerframework.framework.util.FlowExpressionParseUtil.FlowExpressionContext) FlowExpressions(org.checkerframework.dataflow.analysis.FlowExpressions) Receiver(org.checkerframework.dataflow.analysis.FlowExpressions.Receiver)

Example 2 with AnnotatedTypeParameterBounds

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;
}
Also used : AnnotatedTypeParameterBounds(org.checkerframework.framework.type.AnnotatedTypeParameterBounds) TypeElement(javax.lang.model.element.TypeElement)

Example 3 with AnnotatedTypeParameterBounds

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;
}
Also used : AnnotatedTypeParameterBounds(org.checkerframework.framework.type.AnnotatedTypeParameterBounds) AnnotatedExecutableType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable)

Example 4 with AnnotatedTypeParameterBounds

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;
}
Also used : AnnotatedTypeParameterBounds(org.checkerframework.framework.type.AnnotatedTypeParameterBounds) AnnotatedExecutableType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType) AnnotatedDeclaredType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) AnnotatedTypeVariable(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable)

Example 5 with AnnotatedTypeParameterBounds

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)));
            }
        }
    }
}
Also used : AnnotatedTypeParameterBounds(org.checkerframework.framework.type.AnnotatedTypeParameterBounds) AnnotatedWildcardType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedWildcardType) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Aggregations

AnnotatedTypeParameterBounds (org.checkerframework.framework.type.AnnotatedTypeParameterBounds)5 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)3 ArrayList (java.util.ArrayList)2 List (java.util.List)2 AnnotatedExecutableType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType)2 AnnotatedTypeVariable (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable)2 ExecutableElement (javax.lang.model.element.ExecutableElement)1 TypeElement (javax.lang.model.element.TypeElement)1 FlowExpressions (org.checkerframework.dataflow.analysis.FlowExpressions)1 Receiver (org.checkerframework.dataflow.analysis.FlowExpressions.Receiver)1 AnnotatedDeclaredType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType)1 AnnotatedWildcardType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedWildcardType)1 FlowExpressionContext (org.checkerframework.framework.util.FlowExpressionParseUtil.FlowExpressionContext)1