Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correct treatment of T extends Object and ? extends Object in stub files #5684

Closed
wants to merge 17 commits into from
Closed
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -7,6 +7,9 @@ Version 3.31.1 (March 1, 2023)

Rename `TreeUtils.instanceOfGetPattern()` to `TreeUtils.instanceOfTreeGetPattern()`.

Deprecated `AnnotatedTypes#isExplicitlySuperBounded` and `AnnotatedTypes#isExplicitlyExtendsBounded`
because they are duplicates of `#hasExplicitSuperBound` and `#hasExplicitExtendsBound`.

**Closed issues:**


Original file line number Diff line number Diff line change
@@ -605,7 +605,7 @@ protected Void visitParameterizedType(AnnotatedDeclaredType type, ParameterizedT
wildcard.getExtendsBound(),
capturedTypeVar.getUpperBound());
}
} else if (AnnotatedTypes.isExplicitlySuperBounded(wildcard)) {
} else if (AnnotatedTypes.hasExplicitSuperBound(wildcard)) {
// If the super bound of the wildcard is the same as the upper bound of the
// type parameter, then javac uses the bound rather than creating a fresh
// type variable.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.checkerframework.framework.type.typeannotator;

import com.sun.tools.javac.code.Type.WildcardType;
import java.util.ArrayDeque;
import java.util.List;
import java.util.Set;
@@ -14,6 +13,7 @@
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedWildcardType;
import org.checkerframework.framework.util.AnnotatedTypes;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.TypesUtils;
import org.plumelib.util.StringsPlume;
@@ -114,19 +114,18 @@ public Void visitDeclared(AnnotatedDeclaredType declaredType, Void aVoid) {
* Rather than defaulting the missing bounds of a wildcard, find the bound annotations on the type
* parameter it replaced. Place those annotations on the wildcard.
*
* @param wildcardAtm type to annotate
* @param wildcard type to annotate
*/
@Override
public Void visitWildcard(AnnotatedWildcardType wildcardAtm, Void aVoid) {
if (visitedNodes.containsKey(wildcardAtm) || pause) {
public Void visitWildcard(AnnotatedWildcardType wildcard, Void aVoid) {
if (visitedNodes.containsKey(wildcard) || pause) {
return null;
}
visitedNodes.put(wildcardAtm, null);
visitedNodes.put(wildcard, null);

final WildcardType wildcard = (WildcardType) wildcardAtm.getUnderlyingType();
Element typeParamElement = TypesUtils.wildcardToTypeParam(wildcard);
Element typeParamElement = TypesUtils.wildcardToTypeParam(wildcard.getUnderlyingType());
if (typeParamElement == null && !parents.isEmpty()) {
typeParamElement = getTypeParameterElement(wildcardAtm, parents.peekFirst());
typeParamElement = getTypeParameterElement(wildcard, parents.peekFirst());
}

if (typeParamElement != null) {
@@ -138,25 +137,22 @@ public Void visitWildcard(AnnotatedWildcardType wildcardAtm, Void aVoid) {
final Set<? extends AnnotationMirror> tops =
typeFactory.getQualifierHierarchy().getTopAnnotations();

// Do not test `wildcard.isUnbound()` because as of Java 18, it returns true for "?
// extends Object".
switch (wildcard.kind) {
case UNBOUND:
propagateExtendsBound(wildcardAtm, typeParam, tops);
propagateSuperBound(wildcardAtm, typeParam, tops);
break;
case EXTENDS:
propagateSuperBound(wildcardAtm, typeParam, tops);
break;
case SUPER:
propagateExtendsBound(wildcardAtm, typeParam, tops);
break;
default:
throw new BugInCF("unexpected wildcard kind " + wildcard.kind + " for " + wildcard);
if (AnnotatedTypes.hasNoExplicitBound(wildcard)) {
propagateExtendsBound(wildcard, typeParam, tops);
propagateSuperBound(wildcard, typeParam, tops);
} else if (AnnotatedTypes.hasExplicitExtendsBound(wildcard)) {
propagateSuperBound(wildcard, typeParam, tops);
} else if (AnnotatedTypes.hasExplicitSuperBound(wildcard)) {
propagateExtendsBound(wildcard, typeParam, tops);
} else {
// If this is thrown, then it means that there's a bug in one of the
// AnnotatedTypes.hasNoExplicit*Bound methods. Probably something changed in the javac
// implementation.
throw new BugInCF("Wildcard is neither unbound nor does it have an explicit bound.");
}
}
scan(wildcardAtm.getExtendsBound(), null);
scan(wildcardAtm.getSuperBound(), null);
scan(wildcard.getExtendsBound(), null);
scan(wildcard.getSuperBound(), null);
return null;
}

Original file line number Diff line number Diff line change
@@ -9,7 +9,6 @@
import com.sun.tools.javac.code.BoundKind;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Type.WildcardType;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
@@ -240,40 +239,6 @@ private static void fixUpRawTypes(
}
}

// Do not use `isUnbound()` because as of Java 18, it returns true for "? extends Object".

/**
* This method identifies wildcard types that are unbound.
*
* @param wildcard the type to check
* @return true if the given card is an unbounded wildcard
*/
public static boolean hasNoExplicitBound(final AnnotatedTypeMirror wildcard) {
return ((Type.WildcardType) wildcard.getUnderlyingType()).kind == BoundKind.UNBOUND;
}

/**
* This method identifies wildcard types that have an explicit super bound. NOTE:
* Type.WildcardType.isSuperBound will return true for BOTH unbound and super bound wildcards
* which necessitates this method
*/
public static boolean hasExplicitSuperBound(final AnnotatedTypeMirror wildcard) {
final Type.WildcardType wildcardType = (Type.WildcardType) wildcard.getUnderlyingType();
return wildcardType.isSuperBound()
&& ((WildcardType) wildcard.getUnderlyingType()).kind != BoundKind.UNBOUND;
}

/**
* This method identifies wildcard types that have an explicit extends bound. NOTE:
* Type.WildcardType.isExtendsBound will return true for BOTH unbound and extends bound wildcards
* which necessitates this method
*/
public static boolean hasExplicitExtendsBound(final AnnotatedTypeMirror wildcard) {
final Type.WildcardType wildcardType = (Type.WildcardType) wildcard.getUnderlyingType();
return wildcardType.isExtendsBound()
&& ((WildcardType) wildcard.getUnderlyingType()).kind != BoundKind.UNBOUND;
}

/**
* Return the base type of type or any of its outer types that starts with the given type. If none
* exists, return null.
@@ -1525,24 +1490,58 @@ public static AnnotationMirrorSet glbOfBounds(
// For Wildcards, isSuperBound() and isExtendsBound() will return true if isUnbound() does.
// But don't use isUnbound(), because as of Java 18, it returns true for "? extends Object".

/**
* This method identifies wildcard types that are unbound.
*
* @param wildcard the type to check
* @return true if the given card is an unbounded wildcard
*/
public static boolean hasNoExplicitBound(final AnnotatedTypeMirror wildcard) {
return ((Type.WildcardType) wildcard.getUnderlyingType()).kind == BoundKind.UNBOUND;
}

/**
* Returns true if wildcard type is explicitly super bounded.
*
* @param wildcardType the wildcard type to test
* @return true if wildcard type is explicitly super bounded
* @deprecated Use {@link #hasExplicitSuperBound(AnnotatedTypeMirror)}
*/
@Deprecated
public static boolean isExplicitlySuperBounded(final AnnotatedWildcardType wildcardType) {
return ((Type.WildcardType) wildcardType.getUnderlyingType()).isSuperBound()
&& ((Type.WildcardType) wildcardType.getUnderlyingType()).kind != BoundKind.UNBOUND;
return hasExplicitSuperBound(wildcardType);
}

/**
* Returns true if wildcard type has an explicit super bound.
*
* @param wildcard the wildcard type to test
* @return true if wildcard type is explicitly super bounded
*/
public static boolean hasExplicitSuperBound(final AnnotatedTypeMirror wildcard) {
return ((Type.WildcardType) wildcard.getUnderlyingType()).isSuperBound()
&& ((Type.WildcardType) wildcard.getUnderlyingType()).kind != BoundKind.UNBOUND;
}

/**
* Returns true if wildcard type is explicitly extends bounded.
*
* @param wildcardType the wildcard type to test
* @return true if wildcard type is explicitly extends bounded
* @deprecated Use {@link #hasExplicitExtendsBound(AnnotatedTypeMirror)}.
*/
@Deprecated
public static boolean isExplicitlyExtendsBounded(final AnnotatedWildcardType wildcardType) {
return hasExplicitExtendsBound(wildcardType);
}

/**
* Returns true if wildcard type has an explicit extends bound.
*
* @param wildcardType the wildcard type to test
* @return true if wildcard type is explicitly extends bounded
*/
public static boolean hasExplicitExtendsBound(final AnnotatedTypeMirror wildcardType) {
return ((Type.WildcardType) wildcardType.getUnderlyingType()).isExtendsBound()
&& ((Type.WildcardType) wildcardType.getUnderlyingType()).kind != BoundKind.UNBOUND;
}
Original file line number Diff line number Diff line change
@@ -10,7 +10,6 @@
import com.sun.source.tree.TypeParameterTree;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.TreePath;
import com.sun.tools.javac.code.BoundKind;
import com.sun.tools.javac.code.Type.WildcardType;
import java.util.Arrays;
import java.util.Collections;
@@ -43,6 +42,7 @@
import org.checkerframework.framework.type.GenericAnnotatedTypeFactory;
import org.checkerframework.framework.type.QualifierHierarchy;
import org.checkerframework.framework.type.visitor.AnnotatedTypeScanner;
import org.checkerframework.framework.util.AnnotatedTypes;
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.BugInCF;
@@ -1222,25 +1222,25 @@ private BoundType getTypeVarBoundType(final TypeParameterElement typeParamElem)
* Returns the BoundType of annotatedWildcard. If it is unbounded, use the type parameter to which
* its an argument.
*
* @param annotatedWildcard the annotated wildcard type
* @param wildcardType the annotated wildcard type
* @return the BoundType of annotatedWildcard. If it is unbounded, use the type parameter to which
* its an argument
*/
public BoundType getWildcardBoundType(final AnnotatedWildcardType annotatedWildcard) {

final WildcardType wildcard = (WildcardType) annotatedWildcard.getUnderlyingType();
Boolean isBoundInStub = atypeFactory.stubTypes.isBound(wildcard);

if (isBoundInStub != null ? isBoundInStub : wildcard.kind == BoundKind.UNBOUND) {
if (wildcard.bound != null) {
return getTypeVarBoundType((TypeParameterElement) wildcard.bound.asElement());
public BoundType getWildcardBoundType(final AnnotatedWildcardType wildcardType) {
if (AnnotatedTypes.hasNoExplicitBound(wildcardType)) {
final WildcardType wildcard = (WildcardType) wildcardType.getUnderlyingType();
Boolean isBoundInStub = atypeFactory.stubTypes.isBound(wildcard);

TypeParameterElement e = TypesUtils.wildcardToTypeParam(wildcardType.getUnderlyingType());
if (e != null) {
return getTypeVarBoundType(e);
} else {
return BoundType.UNBOUNDED;
}
} else if (AnnotatedTypes.hasExplicitSuperBound(wildcardType)) {
return BoundType.LOWER;
} else {
return BoundType.UPPER;
}

// note: isSuperBound will be true for unbounded and lowers, but the unbounded case is
// already handled
return wildcard.isSuperBound() ? BoundType.LOWER : BoundType.UPPER;
}
}
Original file line number Diff line number Diff line change
@@ -681,6 +681,18 @@ public static TypeMirror upperBound(TypeMirror type) {
* Get the type parameter for this wildcard from the underlying type's bound field This field is
* sometimes null, in that case this method will return null.
*
* @param wildcard wildcard type
* @return the TypeParameterElement the wildcard is an argument to, {@code null} otherwise
*/
public static @Nullable TypeParameterElement wildcardToTypeParam(final WildcardType wildcard) {
return wildcardToTypeParam((Type.WildcardType) wildcard);
}

/**
* Get the type parameter for this wildcard from the underlying type's bound field This field is
* sometimes null, in that case this method will return null.
*
* @param wildcard wildcard type
* @return the TypeParameterElement the wildcard is an argument to, {@code null} otherwise
*/
public static @Nullable TypeParameterElement wildcardToTypeParam(