diff --git a/checker-qual/src/main/java/org/checkerframework/checker/calledmethods/qual/CalledMethodsBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/calledmethods/qual/CalledMethodsBottom.java index 6f2e388c1c2..ecc5d2546f2 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/calledmethods/qual/CalledMethodsBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/calledmethods/qual/CalledMethodsBottom.java @@ -19,5 +19,5 @@ @SubtypeOf({CalledMethods.class, CalledMethodsPredicate.class}) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) public @interface CalledMethodsBottom {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/compilermsgs/qual/CompilerMessageKeyBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/compilermsgs/qual/CompilerMessageKeyBottom.java index b1dc0b2350c..f730e685a02 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/compilermsgs/qual/CompilerMessageKeyBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/compilermsgs/qual/CompilerMessageKeyBottom.java @@ -22,6 +22,6 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(CompilerMessageKey.class) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @DefaultFor(TypeUseLocation.LOWER_BOUND) public @interface CompilerMessageKeyBottom {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/fenum/qual/FenumBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/fenum/qual/FenumBottom.java index 4385d9492c3..b48b127a622 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/fenum/qual/FenumBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/fenum/qual/FenumBottom.java @@ -22,7 +22,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) // Subtype relationships are set up by passing this class as a bottom // to the multigraph hierarchy constructor. @SubtypeOf({}) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/fenum/qual/FenumTop.java b/checker-qual/src/main/java/org/checkerframework/checker/fenum/qual/FenumTop.java index 0123d2518a5..8f0c43b5bff 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/fenum/qual/FenumTop.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/fenum/qual/FenumTop.java @@ -19,7 +19,12 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({ + TypeUseLocation.LOWER_BOUND, + TypeUseLocation.UPPER_BOUND, + TypeUseLocation.LOCAL_VARIABLE, + TypeUseLocation.RESOURCE_VARIABLE +}) @SubtypeOf({}) @DefaultFor({TypeUseLocation.LOCAL_VARIABLE, TypeUseLocation.RESOURCE_VARIABLE}) public @interface FenumTop {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/formatter/qual/FormatBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/formatter/qual/FormatBottom.java index 9d6aa8186cc..9438cf76820 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/formatter/qual/FormatBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/formatter/qual/FormatBottom.java @@ -20,7 +20,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @SubtypeOf({Format.class, InvalidFormat.class}) @DefaultFor(value = {TypeUseLocation.LOWER_BOUND}) public @interface FormatBottom {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/formatter/qual/UnknownFormat.java b/checker-qual/src/main/java/org/checkerframework/checker/formatter/qual/UnknownFormat.java index a110ce19bc9..e0512950429 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/formatter/qual/UnknownFormat.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/formatter/qual/UnknownFormat.java @@ -18,8 +18,8 @@ *

A type annotation indicating that the run-time value might or might not be a valid format * string. * - *

This annotation may not be written in source code; it is an implementation detail of the - * checker. + *

It is usually not necessary to write this annotation in source code. It is an implementation + * detail of the checker. * * @checker_framework.manual #formatter-checker Format String Checker */ @@ -29,5 +29,5 @@ @InvisibleQualifier @SubtypeOf({}) @DefaultQualifierInHierarchy -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.ALL}) public @interface UnknownFormat {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/i18n/qual/LocalizableKeyBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/i18n/qual/LocalizableKeyBottom.java index 36e7b6f7e81..f0727f5b9eb 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/i18n/qual/LocalizableKeyBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/i18n/qual/LocalizableKeyBottom.java @@ -21,7 +21,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @SubtypeOf(LocalizableKey.class) @DefaultFor(TypeUseLocation.LOWER_BOUND) public @interface LocalizableKeyBottom {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/i18nformatter/qual/I18nFormatBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/i18nformatter/qual/I18nFormatBottom.java index d05041e49cf..ff45b277970 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/i18nformatter/qual/I18nFormatBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/i18nformatter/qual/I18nFormatBottom.java @@ -21,7 +21,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @SubtypeOf({I18nFormat.class, I18nInvalidFormat.class, I18nFormatFor.class}) @DefaultFor(value = {TypeUseLocation.LOWER_BOUND}) public @interface I18nFormatBottom {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/i18nformatter/qual/I18nUnknownFormat.java b/checker-qual/src/main/java/org/checkerframework/checker/i18nformatter/qual/I18nUnknownFormat.java index c0f9466c425..66b587b2653 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/i18nformatter/qual/I18nUnknownFormat.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/i18nformatter/qual/I18nUnknownFormat.java @@ -18,12 +18,15 @@ *

A type annotation indicating that the run-time value might or might not be a valid i18n format * string. * + *

It is usually not necessary to write this annotation in source code. It is an implementation + * detail of the checker. + * * @checker_framework.manual #i18n-formatter-checker Internationalization Format String Checker */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.ALL}) @InvisibleQualifier @SubtypeOf({}) @DefaultQualifierInHierarchy diff --git a/checker-qual/src/main/java/org/checkerframework/checker/index/qual/LowerBoundBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/index/qual/LowerBoundBottom.java index e0b937a427c..4bff20599c3 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/index/qual/LowerBoundBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/index/qual/LowerBoundBottom.java @@ -19,6 +19,6 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @SubtypeOf({Positive.class}) public @interface LowerBoundBottom {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/index/qual/SameLenBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/index/qual/SameLenBottom.java index b1ce427d00a..5f4360c00d5 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/index/qual/SameLenBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/index/qual/SameLenBottom.java @@ -19,6 +19,6 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @SubtypeOf(SameLen.class) public @interface SameLenBottom {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/index/qual/SearchIndexBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/index/qual/SearchIndexBottom.java index 66cea84cad9..5b36dc568ba 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/index/qual/SearchIndexBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/index/qual/SearchIndexBottom.java @@ -19,6 +19,6 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @SubtypeOf(NegativeIndexFor.class) public @interface SearchIndexBottom {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/index/qual/SubstringIndexBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/index/qual/SubstringIndexBottom.java index afd093a4a4f..2fe7a440d4c 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/index/qual/SubstringIndexBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/index/qual/SubstringIndexBottom.java @@ -19,6 +19,6 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @SubtypeOf(SubstringIndexFor.class) public @interface SubstringIndexBottom {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/index/qual/UpperBoundBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/index/qual/UpperBoundBottom.java index 75454f12b84..29b373fc5bb 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/index/qual/UpperBoundBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/index/qual/UpperBoundBottom.java @@ -19,6 +19,6 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @SubtypeOf({LTOMLengthOf.class, UpperBoundLiteral.class}) public @interface UpperBoundBottom {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/index/qual/UpperBoundLiteral.java b/checker-qual/src/main/java/org/checkerframework/checker/index/qual/UpperBoundLiteral.java index 3ed82578bdb..2f29d0d337c 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/index/qual/UpperBoundLiteral.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/index/qual/UpperBoundLiteral.java @@ -18,7 +18,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @SubtypeOf(LTEqLengthOf.class) public @interface UpperBoundLiteral { diff --git a/checker-qual/src/main/java/org/checkerframework/checker/initialization/qual/FBCBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/initialization/qual/FBCBottom.java index 6059d36c15a..0f54368bbc6 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/initialization/qual/FBCBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/initialization/qual/FBCBottom.java @@ -24,7 +24,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @SubtypeOf({UnderInitialization.class, Initialized.class}) @QualifierForLiterals(LiteralKind.NULL) public @interface FBCBottom {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/lock/qual/GuardSatisfied.java b/checker-qual/src/main/java/org/checkerframework/checker/lock/qual/GuardSatisfied.java index 6dfaba71bc4..248b373eb12 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/lock/qual/GuardSatisfied.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/lock/qual/GuardSatisfied.java @@ -33,7 +33,14 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE_USE) -@TargetLocations({TypeUseLocation.RECEIVER, TypeUseLocation.PARAMETER, TypeUseLocation.RETURN}) +@TargetLocations({ + TypeUseLocation.RECEIVER, + TypeUseLocation.PARAMETER, + TypeUseLocation.RETURN, + TypeUseLocation.FIELD, + TypeUseLocation.LOCAL_VARIABLE, + TypeUseLocation.CONSTRUCTOR_RESULT +}) @SubtypeOf(GuardedByUnknown.class) // TODO: Should @GuardSatisfied be in its own hierarchy? public @interface GuardSatisfied { /** diff --git a/checker-qual/src/main/java/org/checkerframework/checker/lock/qual/GuardedByBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/lock/qual/GuardedByBottom.java index 00001cf060b..793eb8069c9 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/lock/qual/GuardedByBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/lock/qual/GuardedByBottom.java @@ -22,6 +22,6 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @SubtypeOf({NewObject.class}) public @interface GuardedByBottom {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/lock/qual/LockPossiblyHeld.java b/checker-qual/src/main/java/org/checkerframework/checker/lock/qual/LockPossiblyHeld.java index 1b28171f27a..0cc89dae203 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/lock/qual/LockPossiblyHeld.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/lock/qual/LockPossiblyHeld.java @@ -6,6 +6,7 @@ import org.checkerframework.framework.qual.LiteralKind; import org.checkerframework.framework.qual.QualifierForLiterals; import org.checkerframework.framework.qual.SubtypeOf; +import org.checkerframework.framework.qual.TargetLocations; import org.checkerframework.framework.qual.TypeUseLocation; import java.lang.annotation.Documented; @@ -16,8 +17,8 @@ /** * Indicates that an expression is not known to be {@link LockHeld}. * - *

This annotation may not be written in source code; it is an implementation detail of the - * checker. + *

It is usually not necessary to write this annotation in source code. It is an implementation + * detail of the checker. * * @see LockHeld * @checker_framework.manual #lock-checker Lock Checker @@ -29,5 +30,6 @@ @SubtypeOf({}) @DefaultQualifierInHierarchy @DefaultFor(value = TypeUseLocation.LOWER_BOUND, types = Void.class) +@TargetLocations({TypeUseLocation.ALL}) @QualifierForLiterals(LiteralKind.NULL) public @interface LockPossiblyHeld {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/lock/qual/NewObject.java b/checker-qual/src/main/java/org/checkerframework/checker/lock/qual/NewObject.java index 9a87643d56e..2fe65e1fac0 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/lock/qual/NewObject.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/lock/qual/NewObject.java @@ -22,7 +22,12 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({ + TypeUseLocation.LOWER_BOUND, + TypeUseLocation.UPPER_BOUND, + TypeUseLocation.CONSTRUCTOR_RESULT, + TypeUseLocation.RETURN +}) @SubtypeOf({GuardedBy.class, GuardSatisfied.class}) @DefaultFor(TypeUseLocation.CONSTRUCTOR_RESULT) @QualifierForLiterals({LiteralKind.STRING, LiteralKind.PRIMITIVE}) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/nullness/qual/KeyForBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/nullness/qual/KeyForBottom.java index 1d03442dbf8..5ed2010f703 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/nullness/qual/KeyForBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/nullness/qual/KeyForBottom.java @@ -22,7 +22,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @InvisibleQualifier @SubtypeOf(KeyFor.class) public @interface KeyForBottom {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/propkey/qual/PropertyKeyBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/propkey/qual/PropertyKeyBottom.java index 8d0c0471948..e45d61a8ab8 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/propkey/qual/PropertyKeyBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/propkey/qual/PropertyKeyBottom.java @@ -21,7 +21,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @SubtypeOf(PropertyKey.class) @DefaultFor(TypeUseLocation.LOWER_BOUND) public @interface PropertyKeyBottom {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/regex/qual/RegexBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/regex/qual/RegexBottom.java index 45c69bd0040..301b6b74fc4 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/regex/qual/RegexBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/regex/qual/RegexBottom.java @@ -21,7 +21,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @InvisibleQualifier @SubtypeOf({Regex.class, org.checkerframework.checker.regex.qual.PartialRegex.class}) @DefaultFor(value = {TypeUseLocation.LOWER_BOUND}) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/regex/qual/UnknownRegex.java b/checker-qual/src/main/java/org/checkerframework/checker/regex/qual/UnknownRegex.java index 626fd8657f3..398b04b7398 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/regex/qual/UnknownRegex.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/regex/qual/UnknownRegex.java @@ -20,7 +20,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.ALL}) @InvisibleQualifier @SubtypeOf({}) @DefaultQualifierInHierarchy diff --git a/checker-qual/src/main/java/org/checkerframework/checker/signature/qual/SignatureBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/signature/qual/SignatureBottom.java index 9496508d547..91cdba36d25 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/signature/qual/SignatureBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/signature/qual/SignatureBottom.java @@ -20,7 +20,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @SubtypeOf({ FieldDescriptorForPrimitive.class, PrimitiveType.class, diff --git a/checker-qual/src/main/java/org/checkerframework/checker/signedness/qual/SignednessBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/signedness/qual/SignednessBottom.java index ea92761feaf..33ec7578e0e 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/signedness/qual/SignednessBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/signedness/qual/SignednessBottom.java @@ -21,6 +21,9 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({ + TypeUseLocation.LOWER_BOUND, + TypeUseLocation.UPPER_BOUND, +}) @SubtypeOf({SignedPositiveFromUnsigned.class}) public @interface SignednessBottom {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/units/qual/UnitsBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/units/qual/UnitsBottom.java index 72a10f6b0c6..1c0eb735f01 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/units/qual/UnitsBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/units/qual/UnitsBottom.java @@ -20,7 +20,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @SubtypeOf({}) // needs to be done programmatically @DefaultFor(TypeUseLocation.LOWER_BOUND) public @interface UnitsBottom {} diff --git a/checker-qual/src/main/java/org/checkerframework/common/initializedfields/qual/InitializedFieldsBottom.java b/checker-qual/src/main/java/org/checkerframework/common/initializedfields/qual/InitializedFieldsBottom.java index 7e80adbe808..628c199eca5 100644 --- a/checker-qual/src/main/java/org/checkerframework/common/initializedfields/qual/InitializedFieldsBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/common/initializedfields/qual/InitializedFieldsBottom.java @@ -18,5 +18,5 @@ @SubtypeOf({InitializedFields.class}) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) public @interface InitializedFieldsBottom {} diff --git a/checker-qual/src/main/java/org/checkerframework/common/reflection/qual/ClassValBottom.java b/checker-qual/src/main/java/org/checkerframework/common/reflection/qual/ClassValBottom.java index d143d19cc53..e68c8281686 100644 --- a/checker-qual/src/main/java/org/checkerframework/common/reflection/qual/ClassValBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/common/reflection/qual/ClassValBottom.java @@ -20,7 +20,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @InvisibleQualifier @SubtypeOf({ClassVal.class, ClassBound.class}) public @interface ClassValBottom {} diff --git a/checker-qual/src/main/java/org/checkerframework/common/reflection/qual/MethodValBottom.java b/checker-qual/src/main/java/org/checkerframework/common/reflection/qual/MethodValBottom.java index 6c202c8e44d..3e39e6b04d2 100644 --- a/checker-qual/src/main/java/org/checkerframework/common/reflection/qual/MethodValBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/common/reflection/qual/MethodValBottom.java @@ -20,7 +20,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @InvisibleQualifier @SubtypeOf({MethodVal.class}) public @interface MethodValBottom {} diff --git a/checker-qual/src/main/java/org/checkerframework/common/reflection/qual/UnknownClass.java b/checker-qual/src/main/java/org/checkerframework/common/reflection/qual/UnknownClass.java index 57a6988f3cc..ccea4c45929 100644 --- a/checker-qual/src/main/java/org/checkerframework/common/reflection/qual/UnknownClass.java +++ b/checker-qual/src/main/java/org/checkerframework/common/reflection/qual/UnknownClass.java @@ -23,7 +23,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.ALL}) @InvisibleQualifier @SubtypeOf({}) @DefaultQualifierInHierarchy diff --git a/checker-qual/src/main/java/org/checkerframework/common/reflection/qual/UnknownMethod.java b/checker-qual/src/main/java/org/checkerframework/common/reflection/qual/UnknownMethod.java index 15ad2e035a3..bf556909632 100644 --- a/checker-qual/src/main/java/org/checkerframework/common/reflection/qual/UnknownMethod.java +++ b/checker-qual/src/main/java/org/checkerframework/common/reflection/qual/UnknownMethod.java @@ -24,7 +24,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.ALL}) @InvisibleQualifier @SubtypeOf({}) @DefaultQualifierInHierarchy diff --git a/checker-qual/src/main/java/org/checkerframework/common/returnsreceiver/qual/BottomThis.java b/checker-qual/src/main/java/org/checkerframework/common/returnsreceiver/qual/BottomThis.java index 1147536e871..a3e0f92d8bf 100644 --- a/checker-qual/src/main/java/org/checkerframework/common/returnsreceiver/qual/BottomThis.java +++ b/checker-qual/src/main/java/org/checkerframework/common/returnsreceiver/qual/BottomThis.java @@ -19,5 +19,5 @@ @SubtypeOf({UnknownThis.class}) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) public @interface BottomThis {} diff --git a/checker-qual/src/main/java/org/checkerframework/common/subtyping/qual/Bottom.java b/checker-qual/src/main/java/org/checkerframework/common/subtyping/qual/Bottom.java index 0630b187696..93c521d8964 100644 --- a/checker-qual/src/main/java/org/checkerframework/common/subtyping/qual/Bottom.java +++ b/checker-qual/src/main/java/org/checkerframework/common/subtyping/qual/Bottom.java @@ -29,5 +29,5 @@ @Documented @SubtypeOf({}) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) public @interface Bottom {} diff --git a/checker-qual/src/main/java/org/checkerframework/common/value/qual/BottomVal.java b/checker-qual/src/main/java/org/checkerframework/common/value/qual/BottomVal.java index 5742400dad0..26b00d63827 100644 --- a/checker-qual/src/main/java/org/checkerframework/common/value/qual/BottomVal.java +++ b/checker-qual/src/main/java/org/checkerframework/common/value/qual/BottomVal.java @@ -20,7 +20,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.UPPER_BOUND, TypeUseLocation.LOWER_BOUND}) @SubtypeOf({ ArrayLen.class, BoolVal.class, diff --git a/checker-qual/src/main/java/org/checkerframework/framework/qual/TargetLocations.java b/checker-qual/src/main/java/org/checkerframework/framework/qual/TargetLocations.java index 7382cb51a20..d1f544e7017 100644 --- a/checker-qual/src/main/java/org/checkerframework/framework/qual/TargetLocations.java +++ b/checker-qual/src/main/java/org/checkerframework/framework/qual/TargetLocations.java @@ -7,31 +7,37 @@ import java.lang.annotation.Target; /** - * NOTE: This meta-annotation is not currently - * enforced. - * - *

A meta-annotation that restricts the type-use locations where a type qualifier may be written. + * A meta-annotation that restricts the type-use locations where a type qualifier may be applied. * When written together with {@code @Target({ElementType.TYPE_USE})}, the given type qualifier may - * be written only at locations listed in the {@code @TargetLocations(...)} meta-annotation. + * be applied only at locations listed in the {@code @TargetLocations(...)} meta-annotation. * {@code @Target({ElementType.TYPE_USE})} together with no {@code @TargetLocations(...)} means that - * the qualifier can be written on any type use. + * the qualifier can be applied to any type use. {@code @TargetLocations({})} means that the + * qualifier should not be used in source code. The same goal can be achieved by writing + * {@code @Target({})}, which is enforced by javac itself. {@code @TargetLocations({...})} is + * enforced by the checker. The resulting errors from the checker can either be suppressed using + * {@code @SuppressWarnings("type.invalid.annotations.on.location")} or can be ignored by providing + * the {@code -AignoreTargetLocations} option. * - *

This enables a type system designer to permit a qualifier to be written only in certain + *

This enables a type system designer to permit a qualifier to be applied only in certain * locations. For example, some type systems' top and bottom qualifier (such as {@link - * org.checkerframework.checker.nullness.qual.KeyForBottom}) should only be written on an explicit + * org.checkerframework.checker.regex.qual.RegexBottom}) should only be written on an explicit * wildcard upper or lower bound. This meta-annotation is a declarative, coarse-grained approach to * enable that. For finer-grained control, override {@code visit*} methods that visit trees in * BaseTypeVisitor. * - *

This annotation does not prevent the type system from defaulting, inferring, or computing the - * given type annotation at the given location. It only prevents users from writing an explicit - * annotation at the given location. + *

{@code @TargetLocations} are used for all appearances of qualifiers regardless of whether they + * are provided explicitly or implicitly (inferred or computed). Therefore, only use type-use + * locations {@code LOWER_BOUND/UPPER_BOUND} instead of the {@code IMPLICIT_XX/EXPLICIT_XX} + * alternatives. */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface TargetLocations { - /** Type uses at which the qualifier is permitted to be written in source code. */ + /** + * Type uses at which the qualifier is permitted to be applied in source code. + * + * @return type-use locations declared in this meta-annotation + */ TypeUseLocation[] value(); } diff --git a/checker-qual/src/main/java/org/checkerframework/framework/qual/TypeUseLocation.java b/checker-qual/src/main/java/org/checkerframework/framework/qual/TypeUseLocation.java index 96a3db427f1..59b771a5b6a 100644 --- a/checker-qual/src/main/java/org/checkerframework/framework/qual/TypeUseLocation.java +++ b/checker-qual/src/main/java/org/checkerframework/framework/qual/TypeUseLocation.java @@ -6,6 +6,13 @@ *

The order of enums is important. Defaults are applied in this order. In particular, this means * that OTHERWISE and ALL should be last. * + *

For an annotation on a variable which has element kind ENUM_CONSTANT, the annotation's + * type-use location is either {@code TypeUseLocation.FIELD} or {@code + * TypeUseLocation.CONSTRUCTOR_RESULT}. + * + *

Note: The use locations listed here are not complete, for more details see EISOP Issue #340 + * * @see DefaultQualifier * @see javax.lang.model.element.ElementKind */ @@ -45,7 +52,7 @@ public enum TypeUseLocation { /** * Apply default annotations to unannotated lower bounds for type variables and wildcards both - * explicit ones in {@code extends} clauses, and implicit upper bounds when no explicit {@code + * explicit ones in {@code super} clauses, and implicit lower bounds when no explicit {@code * extends} or {@code super} clause is present. */ LOWER_BOUND, diff --git a/checker/jtreg/sortwarnings/ErrorOrders.java b/checker/jtreg/sortwarnings/ErrorOrders.java index 53c36bcc8a3..f2f8dec12f0 100644 --- a/checker/jtreg/sortwarnings/ErrorOrders.java +++ b/checker/jtreg/sortwarnings/ErrorOrders.java @@ -13,6 +13,8 @@ void test2(int i, int[] a) { a[i] = 2; } + // Ignore the test suite's usage of qualifiers in illegal locations. + @SuppressWarnings("type.invalid.annotations.on.location") int test4( @GTENegativeOne @UpperBoundBottom int p1, @UpperBoundBottom @GTENegativeOne int p2, @@ -45,6 +47,8 @@ void test2(int i, int[] a) { a[i] = 2; } + // Ignore the test suite's usage of qualifiers in illegal locations. + @SuppressWarnings("type.invalid.annotations.on.location") int test4( @GTENegativeOne @UpperBoundBottom int p1, @UpperBoundBottom @GTENegativeOne int p2, diff --git a/checker/jtreg/sortwarnings/ErrorOrders.out b/checker/jtreg/sortwarnings/ErrorOrders.out index b9b36485398..69eb381caaf 100644 --- a/checker/jtreg/sortwarnings/ErrorOrders.out +++ b/checker/jtreg/sortwarnings/ErrorOrders.out @@ -1,16 +1,16 @@ -OrderOfCheckers.java:12:99: compiler.err.proc.messager: [assignment.type.incompatible] incompatible types in assignment. +OrderOfCheckers.java:14:99: compiler.err.proc.messager: [assignment.type.incompatible] incompatible types in assignment. found : @UnknownVal int @UnknownVal [] required: @UnknownVal int @BottomVal [] -OrderOfCheckers.java:12:99: compiler.err.proc.messager: [assignment.type.incompatible] incompatible types in assignment. +OrderOfCheckers.java:14:99: compiler.err.proc.messager: [assignment.type.incompatible] incompatible types in assignment. found : int [] required: @SearchIndexBottom int [] -OrderOfCheckers.java:12:99: compiler.err.proc.messager: [assignment.type.incompatible] incompatible types in assignment. +OrderOfCheckers.java:14:99: compiler.err.proc.messager: [assignment.type.incompatible] incompatible types in assignment. found : int @SameLen("y") [] required: int @SameLenBottom [] -OrderOfCheckers.java:12:99: compiler.err.proc.messager: [assignment.type.incompatible] incompatible types in assignment. +OrderOfCheckers.java:14:99: compiler.err.proc.messager: [assignment.type.incompatible] incompatible types in assignment. found : int [] required: @GTENegativeOne int [] -OrderOfCheckers.java:12:99: compiler.err.proc.messager: [assignment.type.incompatible] incompatible types in assignment. +OrderOfCheckers.java:14:99: compiler.err.proc.messager: [assignment.type.incompatible] incompatible types in assignment. found : int [] required: @UpperBoundBottom int [] ErrorOrders.java:13:11: compiler.err.proc.messager: [array.access.unsafe.low] Potentially unsafe array access: the index could be negative. @@ -19,122 +19,122 @@ required: an integer >= 0 (@NonNegative or @Positive) ErrorOrders.java:13:11: compiler.err.proc.messager: [array.access.unsafe.high] Potentially unsafe array access: the index could be larger than the array's bound found : int required: @IndexFor("a") or @LTLengthOf("a") -- an integer less than a's length -ErrorOrders.java:23:33: compiler.err.proc.messager: [assignment.type.incompatible] incompatible types in assignment. +ErrorOrders.java:25:33: compiler.err.proc.messager: [assignment.type.incompatible] incompatible types in assignment. found : @UpperBoundLiteral(0) int required: @LTLengthOf("p2") int -ErrorOrders.java:24:47: compiler.err.proc.messager: [expression.unparsable.type.invalid] Expression invalid in dependent type annotation: [error for expression: This isn't an expression; error: Invalid 'This isn't an expression' because the expression did not parse. Error message: Encountered unexpected token: "isn" ] -ErrorOrders.java:24:55: compiler.err.proc.messager: [assignment.type.incompatible] incompatible types in assignment. +ErrorOrders.java:26:47: compiler.err.proc.messager: [expression.unparsable.type.invalid] Expression invalid in dependent type annotation: [error for expression: This isn't an expression; error: Invalid 'This isn't an expression' because the expression did not parse. Error message: Encountered unexpected token: "isn" ] +ErrorOrders.java:26:55: compiler.err.proc.messager: [assignment.type.incompatible] incompatible types in assignment. found : @LTLengthOf("p2") int required: @LTLengthOf("[error for expression: This isn't an expression; error: Invalid 'This isn't an expression' because the expression did not parse. Error message: Encountered unexpected token: "isn" ]") int -ErrorOrders.java:29:15: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p1 of test4. +ErrorOrders.java:31:15: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p1 of test4. found : int required: @GTENegativeOne int -ErrorOrders.java:29:15: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p1 of test4. +ErrorOrders.java:31:15: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p1 of test4. found : int required: @UpperBoundBottom int -ErrorOrders.java:29:24: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p2 of test4. +ErrorOrders.java:31:24: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p2 of test4. found : int required: @GTENegativeOne int -ErrorOrders.java:29:24: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p2 of test4. +ErrorOrders.java:31:24: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p2 of test4. found : int required: @UpperBoundBottom int -ErrorOrders.java:29:25: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p1 of test4. +ErrorOrders.java:31:25: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p1 of test4. found : int required: @GTENegativeOne int -ErrorOrders.java:29:25: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p1 of test4. +ErrorOrders.java:31:25: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p1 of test4. found : int required: @UpperBoundBottom int -ErrorOrders.java:29:29: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p2 of test4. +ErrorOrders.java:31:29: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p2 of test4. found : int required: @GTENegativeOne int -ErrorOrders.java:29:29: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p2 of test4. +ErrorOrders.java:31:29: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p2 of test4. found : int required: @UpperBoundBottom int -ErrorOrders.java:29:33: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p3 of test4. +ErrorOrders.java:31:33: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p3 of test4. found : @UnknownVal int @UnknownVal [] required: @UnknownVal int @BottomVal [] -ErrorOrders.java:29:37: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p4 of test4. +ErrorOrders.java:31:37: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p4 of test4. found : int @SameLen("p4") [] required: int @SameLenBottom [] -ErrorOrders.java:29:41: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p5 of test4. +ErrorOrders.java:31:41: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p5 of test4. found : @UnknownVal int required: @BottomVal int -ErrorOrders.java:29:46: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p3 of test4. +ErrorOrders.java:31:46: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p3 of test4. found : @UnknownVal int @UnknownVal [] required: @UnknownVal int @BottomVal [] -ErrorOrders.java:29:50: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p4 of test4. +ErrorOrders.java:31:50: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p4 of test4. found : int @SameLen("p4") [] required: int @SameLenBottom [] -ErrorOrders.java:29:54: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p5 of test4. +ErrorOrders.java:31:54: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p5 of test4. found : @UnknownVal int required: @BottomVal int -ErrorOrders.java:33:47: compiler.err.proc.messager: [expression.unparsable.type.invalid] Expression invalid in dependent type annotation: [error for expression: This isn't an expression; error: Invalid 'This isn't an expression' because the expression did not parse. Error message: Encountered unexpected token: "isn" ] -ErrorOrders.java:33:55: compiler.err.proc.messager: [assignment.type.incompatible] incompatible types in assignment. +ErrorOrders.java:35:47: compiler.err.proc.messager: [expression.unparsable.type.invalid] Expression invalid in dependent type annotation: [error for expression: This isn't an expression; error: Invalid 'This isn't an expression' because the expression did not parse. Error message: Encountered unexpected token: "isn" ] +ErrorOrders.java:35:55: compiler.err.proc.messager: [assignment.type.incompatible] incompatible types in assignment. found : @UpperBoundLiteral(0) int required: @LTLengthOf("[error for expression: This isn't an expression; error: Invalid 'This isn't an expression' because the expression did not parse. Error message: Encountered unexpected token: "isn" ]") int -ErrorOrders.java:36:15: compiler.err.proc.messager: [array.access.unsafe.low] Potentially unsafe array access: the index could be negative. +ErrorOrders.java:38:15: compiler.err.proc.messager: [array.access.unsafe.low] Potentially unsafe array access: the index could be negative. found : int required: an integer >= 0 (@NonNegative or @Positive) -ErrorOrders.java:36:15: compiler.err.proc.messager: [array.access.unsafe.high] Potentially unsafe array access: the index could be larger than the array's bound +ErrorOrders.java:38:15: compiler.err.proc.messager: [array.access.unsafe.high] Potentially unsafe array access: the index could be larger than the array's bound found : int required: @IndexFor("a") or @LTLengthOf("a") -- an integer less than a's length -ErrorOrders.java:42:43: compiler.err.proc.messager: [expression.unparsable.type.invalid] Expression invalid in dependent type annotation: [error for expression: This isn't an expression; error: Invalid 'This isn't an expression' because the expression did not parse. Error message: Encountered unexpected token: "isn" ] -ErrorOrders.java:42:51: compiler.err.proc.messager: [assignment.type.incompatible] incompatible types in assignment. +ErrorOrders.java:44:43: compiler.err.proc.messager: [expression.unparsable.type.invalid] Expression invalid in dependent type annotation: [error for expression: This isn't an expression; error: Invalid 'This isn't an expression' because the expression did not parse. Error message: Encountered unexpected token: "isn" ] +ErrorOrders.java:44:51: compiler.err.proc.messager: [assignment.type.incompatible] incompatible types in assignment. found : @UpperBoundLiteral(0) int required: @LTLengthOf("[error for expression: This isn't an expression; error: Invalid 'This isn't an expression' because the expression did not parse. Error message: Encountered unexpected token: "isn" ]") int -ErrorOrders.java:45:11: compiler.err.proc.messager: [array.access.unsafe.low] Potentially unsafe array access: the index could be negative. +ErrorOrders.java:47:11: compiler.err.proc.messager: [array.access.unsafe.low] Potentially unsafe array access: the index could be negative. found : int required: an integer >= 0 (@NonNegative or @Positive) -ErrorOrders.java:45:11: compiler.err.proc.messager: [array.access.unsafe.high] Potentially unsafe array access: the index could be larger than the array's bound +ErrorOrders.java:47:11: compiler.err.proc.messager: [array.access.unsafe.high] Potentially unsafe array access: the index could be larger than the array's bound found : int required: @IndexFor("a") or @LTLengthOf("a") -- an integer less than a's length -ErrorOrders.java:55:33: compiler.err.proc.messager: [assignment.type.incompatible] incompatible types in assignment. +ErrorOrders.java:59:33: compiler.err.proc.messager: [assignment.type.incompatible] incompatible types in assignment. found : @UpperBoundLiteral(0) int required: @LTLengthOf("p2") int -ErrorOrders.java:56:47: compiler.err.proc.messager: [expression.unparsable.type.invalid] Expression invalid in dependent type annotation: [error for expression: This isn't an expression; error: Invalid 'This isn't an expression' because the expression did not parse. Error message: Encountered unexpected token: "isn" ] -ErrorOrders.java:56:55: compiler.err.proc.messager: [assignment.type.incompatible] incompatible types in assignment. +ErrorOrders.java:60:47: compiler.err.proc.messager: [expression.unparsable.type.invalid] Expression invalid in dependent type annotation: [error for expression: This isn't an expression; error: Invalid 'This isn't an expression' because the expression did not parse. Error message: Encountered unexpected token: "isn" ] +ErrorOrders.java:60:55: compiler.err.proc.messager: [assignment.type.incompatible] incompatible types in assignment. found : @LTLengthOf("p2") int required: @LTLengthOf("[error for expression: This isn't an expression; error: Invalid 'This isn't an expression' because the expression did not parse. Error message: Encountered unexpected token: "isn" ]") int -ErrorOrders.java:61:15: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p1 of test4. +ErrorOrders.java:65:15: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p1 of test4. found : int required: @GTENegativeOne int -ErrorOrders.java:61:15: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p1 of test4. +ErrorOrders.java:65:15: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p1 of test4. found : int required: @UpperBoundBottom int -ErrorOrders.java:61:24: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p2 of test4. +ErrorOrders.java:65:24: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p2 of test4. found : int required: @GTENegativeOne int -ErrorOrders.java:61:24: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p2 of test4. +ErrorOrders.java:65:24: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p2 of test4. found : int required: @UpperBoundBottom int -ErrorOrders.java:61:25: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p1 of test4. +ErrorOrders.java:65:25: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p1 of test4. found : int required: @GTENegativeOne int -ErrorOrders.java:61:25: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p1 of test4. +ErrorOrders.java:65:25: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p1 of test4. found : int required: @UpperBoundBottom int -ErrorOrders.java:61:29: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p2 of test4. +ErrorOrders.java:65:29: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p2 of test4. found : int required: @GTENegativeOne int -ErrorOrders.java:61:29: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p2 of test4. +ErrorOrders.java:65:29: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p2 of test4. found : int required: @UpperBoundBottom int -ErrorOrders.java:61:33: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p3 of test4. +ErrorOrders.java:65:33: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p3 of test4. found : @UnknownVal int @UnknownVal [] required: @UnknownVal int @BottomVal [] -ErrorOrders.java:61:37: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p4 of test4. +ErrorOrders.java:65:37: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p4 of test4. found : int @SameLen("p4") [] required: int @SameLenBottom [] -ErrorOrders.java:61:41: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p5 of test4. +ErrorOrders.java:65:41: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p5 of test4. found : @UnknownVal int required: @BottomVal int -ErrorOrders.java:61:46: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p3 of test4. +ErrorOrders.java:65:46: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p3 of test4. found : @UnknownVal int @UnknownVal [] required: @UnknownVal int @BottomVal [] -ErrorOrders.java:61:50: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p4 of test4. +ErrorOrders.java:65:50: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p4 of test4. found : int @SameLen("p4") [] required: int @SameLenBottom [] -ErrorOrders.java:61:54: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p5 of test4. +ErrorOrders.java:65:54: compiler.err.proc.messager: [argument.type.incompatible] incompatible argument for parameter p5 of test4. found : @UnknownVal int required: @BottomVal int 49 errors diff --git a/checker/jtreg/sortwarnings/OrderOfCheckers.java b/checker/jtreg/sortwarnings/OrderOfCheckers.java index 3f59a3c40d0..b1c2df2104d 100644 --- a/checker/jtreg/sortwarnings/OrderOfCheckers.java +++ b/checker/jtreg/sortwarnings/OrderOfCheckers.java @@ -8,6 +8,8 @@ /** This class tests that errors issued on the same tree are sorted by checker. */ public class OrderOfCheckers { + // Ignore the test suite's usage of qualifiers in illegal locations. + @SuppressWarnings("type.invalid.annotations.on.location") void test(int[] y) { @GTENegativeOne @UpperBoundBottom @SearchIndexBottom int @BottomVal @SameLenBottom [] x = y; } diff --git a/checker/jtreg/sortwarnings/OrderOfCheckers.out b/checker/jtreg/sortwarnings/OrderOfCheckers.out index f250b7b9217..479526be3c2 100644 --- a/checker/jtreg/sortwarnings/OrderOfCheckers.out +++ b/checker/jtreg/sortwarnings/OrderOfCheckers.out @@ -1,16 +1,16 @@ -OrderOfCheckers.java:12:99: compiler.err.proc.messager: [[value, allcheckers]:assignment.type.incompatible] incompatible types in assignment. +OrderOfCheckers.java:14:99: compiler.err.proc.messager: [[value, allcheckers]:assignment.type.incompatible] incompatible types in assignment. found : @UnknownVal int @UnknownVal [] required: @UnknownVal int @BottomVal [] -OrderOfCheckers.java:12:99: compiler.err.proc.messager: [[index, searchindex, allcheckers]:assignment.type.incompatible] incompatible types in assignment. +OrderOfCheckers.java:14:99: compiler.err.proc.messager: [[index, searchindex, allcheckers]:assignment.type.incompatible] incompatible types in assignment. found : int [] required: @SearchIndexBottom int [] -OrderOfCheckers.java:12:99: compiler.err.proc.messager: [[index, samelen, allcheckers]:assignment.type.incompatible] incompatible types in assignment. +OrderOfCheckers.java:14:99: compiler.err.proc.messager: [[index, samelen, allcheckers]:assignment.type.incompatible] incompatible types in assignment. found : int @SameLen("y") [] required: int @SameLenBottom [] -OrderOfCheckers.java:12:99: compiler.err.proc.messager: [[index, lowerbound, allcheckers]:assignment.type.incompatible] incompatible types in assignment. +OrderOfCheckers.java:14:99: compiler.err.proc.messager: [[index, lowerbound, allcheckers]:assignment.type.incompatible] incompatible types in assignment. found : int [] required: @GTENegativeOne int [] -OrderOfCheckers.java:12:99: compiler.err.proc.messager: [[index, upperbound, allcheckers]:assignment.type.incompatible] incompatible types in assignment. +OrderOfCheckers.java:14:99: compiler.err.proc.messager: [[index, upperbound, allcheckers]:assignment.type.incompatible] incompatible types in assignment. found : int [] required: @UpperBoundBottom int [] 5 errors diff --git a/checker/src/test/java/org/checkerframework/checker/test/junit/CalledMethodsTest.java b/checker/src/test/java/org/checkerframework/checker/test/junit/CalledMethodsTest.java index f65fd30488a..ac396d83db1 100644 --- a/checker/src/test/java/org/checkerframework/checker/test/junit/CalledMethodsTest.java +++ b/checker/src/test/java/org/checkerframework/checker/test/junit/CalledMethodsTest.java @@ -15,6 +15,8 @@ public CalledMethodsTest(List testFiles) { CalledMethodsChecker.class, "calledmethods", "-nowarn", + // Ignore the test suite's usage of qualifiers in illegal locations. + "-AignoreTargetLocations", "-encoding", "UTF-8"); } diff --git a/checker/src/test/java/org/checkerframework/checker/test/junit/FenumSwingTest.java b/checker/src/test/java/org/checkerframework/checker/test/junit/FenumSwingTest.java index f7b3b66d998..dfc7f55fb4c 100644 --- a/checker/src/test/java/org/checkerframework/checker/test/junit/FenumSwingTest.java +++ b/checker/src/test/java/org/checkerframework/checker/test/junit/FenumSwingTest.java @@ -18,7 +18,9 @@ public FenumSwingTest(List testFiles) { testFiles, org.checkerframework.checker.fenum.FenumChecker.class, "fenum", - "-Aquals=org.checkerframework.checker.fenum.qual.SwingVerticalOrientation,org.checkerframework.checker.fenum.qual.SwingHorizontalOrientation,org.checkerframework.checker.fenum.qual.SwingBoxOrientation,org.checkerframework.checker.fenum.qual.SwingCompassDirection,org.checkerframework.checker.fenum.qual.SwingElementOrientation,org.checkerframework.checker.fenum.qual.SwingTextOrientation"); + "-Aquals=org.checkerframework.checker.fenum.qual.SwingVerticalOrientation,org.checkerframework.checker.fenum.qual.SwingHorizontalOrientation,org.checkerframework.checker.fenum.qual.SwingBoxOrientation,org.checkerframework.checker.fenum.qual.SwingCompassDirection,org.checkerframework.checker.fenum.qual.SwingElementOrientation,org.checkerframework.checker.fenum.qual.SwingTextOrientation", + // Ignore the test suite's usage of qualifiers in illegal locations. + "-AignoreTargetLocations"); // TODO: check all qualifiers } diff --git a/checker/src/test/java/org/checkerframework/checker/test/junit/I18nTest.java b/checker/src/test/java/org/checkerframework/checker/test/junit/I18nTest.java index a031bcdedfb..bd0e3687a65 100644 --- a/checker/src/test/java/org/checkerframework/checker/test/junit/I18nTest.java +++ b/checker/src/test/java/org/checkerframework/checker/test/junit/I18nTest.java @@ -14,7 +14,12 @@ public class I18nTest extends CheckerFrameworkPerDirectoryTest { * @param testFiles the files containing test code, which will be type-checked */ public I18nTest(List testFiles) { - super(testFiles, org.checkerframework.checker.i18n.I18nChecker.class, "i18n"); + super( + testFiles, + org.checkerframework.checker.i18n.I18nChecker.class, + "i18n", + // Ignore the test suite's usage of qualifiers in illegal locations. + "-AignoreTargetLocations"); } @Parameters diff --git a/checker/src/test/java/org/checkerframework/checker/test/junit/IndexInitializedFieldsTest.java b/checker/src/test/java/org/checkerframework/checker/test/junit/IndexInitializedFieldsTest.java index dc34d3b7478..cdd19fb988a 100644 --- a/checker/src/test/java/org/checkerframework/checker/test/junit/IndexInitializedFieldsTest.java +++ b/checker/src/test/java/org/checkerframework/checker/test/junit/IndexInitializedFieldsTest.java @@ -24,7 +24,9 @@ public IndexInitializedFieldsTest(List testFiles) { "org.checkerframework.common.initializedfields.InitializedFieldsChecker"), "index-initializedfields", Collections.emptyList(), - "-Aajava=tests/index-initializedfields/input-annotation-files/"); + "-Aajava=tests/index-initializedfields/input-annotation-files/", + // Ignore the test suite's usage of qualifiers in illegal locations. + "-AignoreTargetLocations"); } @Parameters diff --git a/checker/src/test/java/org/checkerframework/checker/test/junit/IndexTest.java b/checker/src/test/java/org/checkerframework/checker/test/junit/IndexTest.java index 38209b68031..4cae656a319 100644 --- a/checker/src/test/java/org/checkerframework/checker/test/junit/IndexTest.java +++ b/checker/src/test/java/org/checkerframework/checker/test/junit/IndexTest.java @@ -15,7 +15,12 @@ public class IndexTest extends CheckerFrameworkPerDirectoryTest { * @param testFiles the files containing test code, which will be type-checked */ public IndexTest(List testFiles) { - super(testFiles, org.checkerframework.checker.index.IndexChecker.class, "index"); + super( + testFiles, + org.checkerframework.checker.index.IndexChecker.class, + "index", + // Ignore the test suite's usage of qualifiers in illegal locations. + "-AignoreTargetLocations"); } @Parameters diff --git a/checker/src/test/java/org/checkerframework/checker/test/junit/LockTest.java b/checker/src/test/java/org/checkerframework/checker/test/junit/LockTest.java index 67efab91427..7327a154632 100644 --- a/checker/src/test/java/org/checkerframework/checker/test/junit/LockTest.java +++ b/checker/src/test/java/org/checkerframework/checker/test/junit/LockTest.java @@ -14,7 +14,12 @@ public class LockTest extends CheckerFrameworkPerDirectoryTest { * @param testFiles the files containing test code, which will be type-checked */ public LockTest(List testFiles) { - super(testFiles, org.checkerframework.checker.lock.LockChecker.class, "lock"); + super( + testFiles, + org.checkerframework.checker.lock.LockChecker.class, + "lock", + // Ignore the test suite's usage of qualifiers in illegal locations. + "-AignoreTargetLocations"); } @Parameters diff --git a/checker/src/test/java/org/checkerframework/checker/test/junit/SignednessTest.java b/checker/src/test/java/org/checkerframework/checker/test/junit/SignednessTest.java index 1d9c0ef2446..c5f0946897b 100644 --- a/checker/src/test/java/org/checkerframework/checker/test/junit/SignednessTest.java +++ b/checker/src/test/java/org/checkerframework/checker/test/junit/SignednessTest.java @@ -17,7 +17,9 @@ public SignednessTest(List testFiles) { super( testFiles, org.checkerframework.checker.signedness.SignednessChecker.class, - "signedness"); + "signedness", + // Ignore the test suite's usage of qualifiers in illegal locations. + "-AignoreTargetLocations"); } @Parameters diff --git a/checker/src/test/java/org/checkerframework/checker/test/junit/ValueIndexInteractionTest.java b/checker/src/test/java/org/checkerframework/checker/test/junit/ValueIndexInteractionTest.java index 8e85a4f4fbc..edcaa5767f4 100644 --- a/checker/src/test/java/org/checkerframework/checker/test/junit/ValueIndexInteractionTest.java +++ b/checker/src/test/java/org/checkerframework/checker/test/junit/ValueIndexInteractionTest.java @@ -18,7 +18,9 @@ public ValueIndexInteractionTest(List testFiles) { super( testFiles, org.checkerframework.common.value.ValueChecker.class, - "value-index-interaction"); + "value-index-interaction", + // Ignore the test suite's usage of qualifiers in illegal locations. + "-AignoreTargetLocations"); } @Parameters diff --git a/checker/src/test/java/org/checkerframework/checker/testchecker/ainfer/qual/AinferBottom.java b/checker/src/test/java/org/checkerframework/checker/testchecker/ainfer/qual/AinferBottom.java index dc9cf44522d..17af7931bc5 100644 --- a/checker/src/test/java/org/checkerframework/checker/testchecker/ainfer/qual/AinferBottom.java +++ b/checker/src/test/java/org/checkerframework/checker/testchecker/ainfer/qual/AinferBottom.java @@ -15,6 +15,6 @@ */ @SubtypeOf({AinferImplicitAnno.class}) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @DefaultFor(TypeUseLocation.LOWER_BOUND) public @interface AinferBottom {} diff --git a/checker/tests/i18n/Issue2163FinalI18n.java b/checker/tests/i18n/Issue2163FinalI18n.java index 6a0de71a1e7..5d0191be291 100644 --- a/checker/tests/i18n/Issue2163FinalI18n.java +++ b/checker/tests/i18n/Issue2163FinalI18n.java @@ -38,8 +38,9 @@ } @LocalizableKeyBottom class Issue2163FinalCB { - // :: error: (type.invalid.annotations.on.use) :: warning: (inconsistent.constructor.type) :: - // error: (super.invocation.invalid) + // :: warning: (inconsistent.constructor.type) + // :: error: (super.invocation.invalid) + // :: error: (type.invalid.annotations.on.use) @LocalizableKey Issue2163FinalCB() {} } diff --git a/checker/tests/nullness/KeyForLub.java b/checker/tests/nullness/KeyForLub.java index 03159a611d4..94b2b62fca7 100644 --- a/checker/tests/nullness/KeyForLub.java +++ b/checker/tests/nullness/KeyForLub.java @@ -32,11 +32,12 @@ void method( return flag ? key1 : poly; } + // :: error: (type.invalid.annotations.on.location) void poly2(@PolyKeyFor String poly, @UnknownKeyFor String unknown, @KeyForBottom String bot) { // :: error: (assignment.type.incompatible) @PolyKeyFor String s1 = flag ? poly : unknown; @PolyKeyFor String s2 = flag ? poly : bot; - // :: error: (assignment.type.incompatible) + // :: error: (assignment.type.incompatible) :: error: (type.invalid.annotations.on.location) @KeyForBottom String s3 = flag ? poly : bot; } } diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 908de8bedcd..6d9691c2a69 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -19,6 +19,13 @@ Fixed a bug in the Nullness Checker where an instance receiver is incorrectly ma a static method or field access. This could lead to new nullness errors. The static access should be changed to be through a class name. +Checkers now enforce `@TargetLocations` meta-annotations: if a qualifier is declared with the +meta-annotation `@TargetLocations({TypeUseLocation...})`, the qualifier should only be applied to +these type use locations. +The new command-line argument `-AignoreTargetLocations` disables validating the target locations +of qualifiers. This option is not enabled by default. With this flag, the checker ignores all +`@TargetLocations` meta-annotations and allows all qualifiers to be applied to every type use. + **Implementation details:** Corrected the arguments to an `ObjectCreationNode` when the node refers to an @@ -38,7 +45,7 @@ Changed the return types of **Closed issues:** -eisop#297, eisop#376, eisop#400, eisop#519, eisop#532, eisop#533, typetools#1590. +eisop#297, eisop#376, eisop#400, eisop#519, eisop#532, eisop#533, typetools#1590, typetools#1919. Version 3.34.0-eisop1 (May 9, 2023) diff --git a/docs/manual/creating-a-checker.tex b/docs/manual/creating-a-checker.tex index a8f43de3e7c..dae63b24c98 100644 --- a/docs/manual/creating-a-checker.tex +++ b/docs/manual/creating-a-checker.tex @@ -814,7 +814,7 @@ % \begin{Verbatim} @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) \end{Verbatim} Furthermore, by convention the name of such a qualifier ends with ``\''. diff --git a/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeValidator.java b/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeValidator.java index 3189ebea7d8..5b74b0bfa8b 100644 --- a/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeValidator.java +++ b/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeValidator.java @@ -13,6 +13,7 @@ import org.checkerframework.checker.compilermsgs.qual.CompilerMessageKey; import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.TypeUseLocation; import org.checkerframework.framework.source.DiagMessage; import org.checkerframework.framework.type.AnnotatedTypeFactory; import org.checkerframework.framework.type.AnnotatedTypeMirror; @@ -36,6 +37,7 @@ import org.checkerframework.javacutil.TypesUtils; import org.plumelib.util.ArrayMap; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -686,6 +688,7 @@ public Void visitWildcard(AnnotatedWildcardType type, Tree tree) { reportInvalidBounds(type, tree); } + validateWildCardTargetLocation(type, tree); return super.visitWildcard(type, tree); } @@ -712,4 +715,62 @@ public boolean areBoundsValid( return true; } + + /** + * Validate if qualifiers on wildcard are permitted by {@link + * org.checkerframework.framework.qual.TargetLocations}. Report an error if the actual use of + * this annotation is not listed in the declared TypeUseLocations in this meta-annotation. + * + * @param type the type to check + * @param tree the tree of this type + */ + protected void validateWildCardTargetLocation(AnnotatedWildcardType type, Tree tree) { + if (visitor.ignoreTargetLocations) { + return; + } + + for (AnnotationMirror am : type.getSuperBound().getAnnotations()) { + List locations = + visitor.qualAllowedLocations.get(AnnotationUtils.annotationName(am)); + // @Target({ElementType.TYPE_USE})} together with no @TargetLocations(...) means + // that the qualifier can be written on any type use. + // Otherwise, for a valid use of qualifier on the super bound, that qualifier must + // declare one of these four type-use locations in the @TargetLocations meta-annotation. + List lowerLocations = + Arrays.asList( + TypeUseLocation.ALL, + TypeUseLocation.LOWER_BOUND, + TypeUseLocation.IMPLICIT_LOWER_BOUND, + TypeUseLocation.EXPLICIT_LOWER_BOUND); + if (locations == null || locations.stream().anyMatch(lowerLocations::contains)) { + continue; + } + + checker.reportError( + tree, + "type.invalid.annotations.on.location", + type.getSuperBound().getAnnotations().toString(), + "SUPER_WILDCARD"); + } + + for (AnnotationMirror am : type.getExtendsBound().getAnnotations()) { + List locations = + visitor.qualAllowedLocations.get(AnnotationUtils.annotationName(am)); + List upperLocations = + Arrays.asList( + TypeUseLocation.ALL, + TypeUseLocation.UPPER_BOUND, + TypeUseLocation.IMPLICIT_UPPER_BOUND, + TypeUseLocation.EXPLICIT_UPPER_BOUND); + if (locations == null || locations.stream().anyMatch(upperLocations::contains)) { + continue; + } + + checker.reportError( + tree, + "type.invalid.annotations.on.location", + type.getExtendsBound().getAnnotations().toString(), + "EXTENDS_WILDCARD"); + } + } } diff --git a/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java b/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java index 3a81afb0ca0..f7f7b81fde4 100644 --- a/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java +++ b/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java @@ -47,6 +47,7 @@ import org.checkerframework.checker.interning.qual.FindDistinct; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.checker.signature.qual.CanonicalName; import org.checkerframework.dataflow.analysis.TransferResult; import org.checkerframework.dataflow.cfg.node.BooleanLiteralNode; import org.checkerframework.dataflow.cfg.node.Node; @@ -68,6 +69,8 @@ import org.checkerframework.framework.flow.CFAbstractStore; import org.checkerframework.framework.flow.CFAbstractValue; import org.checkerframework.framework.qual.DefaultQualifier; +import org.checkerframework.framework.qual.TargetLocations; +import org.checkerframework.framework.qual.TypeUseLocation; import org.checkerframework.framework.qual.Unused; import org.checkerframework.framework.source.DiagMessage; import org.checkerframework.framework.source.SourceVisitor; @@ -265,16 +268,27 @@ public class BaseTypeVisitor> qualAllowedLocations; + + /** + * Constructor for creating a BaseTypeVisitor. + * * @param checker the type-checker associated with this visitor (for callbacks to {@link * TypeHierarchy#isSubtype}) */ @@ -283,6 +297,8 @@ public BaseTypeVisitor(BaseTypeChecker checker) { } /** + * Constructor for creating a BaseTypeVisitor. + * * @param checker the type-checker associated with this visitor * @param typeFactory the type factory, or null. If null, this calls {@link #createTypeFactory}. */ @@ -307,6 +323,9 @@ protected BaseTypeVisitor(BaseTypeChecker checker, Factory typeFactory) { suggestPureMethods = checker.hasOption("suggestPureMethods"); // NO-AFU || infer; checkPurity = checker.hasOption("checkPurityAnnotations") || suggestPureMethods; warnRedundantAnnotations = checker.hasOption("warnRedundantAnnotations"); + ignoreTargetLocations = checker.hasOption("ignoreTargetLocations"); + qualAllowedLocations = createQualAllowedLocations(); + checkEnclosingExpr = checker.hasOption("checkEnclosingExpr"); ajavaChecks = checker.hasOption("ajavaChecks"); assumeSideEffectFree = @@ -1021,7 +1040,6 @@ public Void visitMethod(MethodTree tree, Void p) { tree.getParameters()); checkContractsAtMethodDeclaration( tree, methodElement, formalParamNames, abstractMethod); - /* NO-AFU // Infer postconditions if (atypeFactory.getWholeProgramInference() != null) { @@ -1584,10 +1602,140 @@ && getCurrentPath().getParentPath().getLeaf().getKind() // so only validate if commonAssignmentCheck wasn't called validateTypeOf(tree); } + validateVariablesTargetLocation(tree, variableType); warnRedundantAnnotations(tree, variableType); return super.visitVariable(tree, p); } + /** + * Validate if the annotations on the VariableTree are at the right locations, which is + * specified by the meta-annotation @TargetLocations. The difference of this method between + * {@link BaseTypeVisitor#validateTargetLocation(Tree, AnnotatedTypeMirror, TypeUseLocation)} is + * that this one is only used in {@link BaseTypeVisitor#visitVariable(VariableTree, Void)} + * + * @param tree annotations on this VariableTree will be validated + * @param type the type of the tree + */ + protected void validateVariablesTargetLocation(Tree tree, AnnotatedTypeMirror type) { + if (ignoreTargetLocations) { + return; + } + Element element = TreeUtils.elementFromTree(tree); + + if (element != null) { + ElementKind elemKind = element.getKind(); + // TypeUseLocation.java doesn't have ENUM type use location right now. + for (AnnotationMirror am : type.getAnnotations()) { + List locations = + qualAllowedLocations.get(AnnotationUtils.annotationName(am)); + if (locations == null || locations.contains(TypeUseLocation.ALL)) { + continue; + } + boolean issueError = true; + switch (elemKind) { + case LOCAL_VARIABLE: + if (locations.contains(TypeUseLocation.LOCAL_VARIABLE)) issueError = false; + break; + case EXCEPTION_PARAMETER: + if (locations.contains(TypeUseLocation.EXCEPTION_PARAMETER)) + issueError = false; + break; + case PARAMETER: + if (((VariableTree) tree).getName().contentEquals("this")) { + if (locations.contains(TypeUseLocation.RECEIVER)) { + issueError = false; + } + } else { + if (locations.contains(TypeUseLocation.PARAMETER)) { + issueError = false; + } + } + break; + case RESOURCE_VARIABLE: + if (locations.contains(TypeUseLocation.RESOURCE_VARIABLE)) { + issueError = false; + } + break; + case FIELD: + if (locations.contains(TypeUseLocation.FIELD)) { + issueError = false; + } + break; + case ENUM_CONSTANT: + if (locations.contains(TypeUseLocation.FIELD) + || locations.contains(TypeUseLocation.CONSTRUCTOR_RESULT)) { + issueError = false; + } + break; + default: + throw new BugInCF("Location not matched"); + } + if (issueError) { + checker.reportError( + tree, + "type.invalid.annotations.on.location", + am.toString(), + element.getKind().name()); + } + } + } + } + + /** + * Validate if the annotations on the tree are at the right locations, which are specified by + * the meta-annotation @TargetLocations. + * + * @param tree annotations on this VariableTree will be validated + * @param type the type of the tree + * @param required if all of the TypeUseLocations in {@code required} are not present in the + * specification of the annotation (@TargetLocations), issue an error. + */ + protected void validateTargetLocation( + Tree tree, AnnotatedTypeMirror type, TypeUseLocation required) { + if (ignoreTargetLocations) { + return; + } + for (AnnotationMirror am : type.getAnnotations()) { + List locations = + qualAllowedLocations.get(AnnotationUtils.annotationName(am)); + if (locations == null || locations.contains(TypeUseLocation.ALL)) { + continue; + } + boolean issueError = !locations.contains(required); + + if (issueError) { + checker.reportError( + tree, + "type.invalid.annotations.on.location", + am.toString(), + required.toString()); + } + } + } + + /** + * Create a new map, which is used for declared type-use locations lookup. + * + * @return a new mapping from strings of qualifier names to their declared type-use locations. + */ + protected Map<@CanonicalName String, List> createQualAllowedLocations() { + HashMap<@CanonicalName String, List> qualAllowedLocations = + new HashMap<>(); + for (String qual : atypeFactory.getSupportedTypeQualifierNames()) { + Element elem = elements.getTypeElement(qual); + TargetLocations tls = elem.getAnnotation(TargetLocations.class); + // @Target({ElementType.TYPE_USE})} together with no @TargetLocations(...) means that + // the qualifier can be written on any type use. + if (tls == null) { + qualAllowedLocations.put(qual, null); + continue; + } + List locations = Arrays.asList(tls.value()); + qualAllowedLocations.put(qual, locations); + } + return qualAllowedLocations; + } + /** * Issues a "redundant.anno" warning if the annotation written on the type is the same as the * default annotation for this type and location. @@ -4882,6 +5030,7 @@ public boolean isValidUse(AnnotatedArrayType type, Tree tree) { * check the return type. * * @param tree the AST type supplied by the user + * @return true if the type is valid */ public boolean validateTypeOf(Tree tree) { AnnotatedTypeMirror type; @@ -4889,7 +5038,6 @@ public boolean validateTypeOf(Tree tree) { switch (tree.getKind()) { case PRIMITIVE_TYPE: case PARAMETERIZED_TYPE: - case TYPE_PARAMETER: case ARRAY_TYPE: case UNBOUNDED_WILDCARD: case EXTENDS_WILDCARD: @@ -4897,6 +5045,17 @@ public boolean validateTypeOf(Tree tree) { case ANNOTATED_TYPE: type = atypeFactory.getAnnotatedTypeFromTypeTree(tree); break; + case TYPE_PARAMETER: + type = atypeFactory.getAnnotatedTypeFromTypeTree(tree); + validateTargetLocation( + tree, + ((AnnotatedTypeVariable) type).getUpperBound(), + TypeUseLocation.UPPER_BOUND); + validateTargetLocation( + tree, + ((AnnotatedTypeVariable) type).getLowerBound(), + TypeUseLocation.LOWER_BOUND); + break; case METHOD: type = atypeFactory.getMethodReturnType((MethodTree) tree); if (type == null || type.getKind() == TypeKind.VOID) { @@ -4905,6 +5064,11 @@ public boolean validateTypeOf(Tree tree) { // not use void as return type. return true; } + if (TreeUtils.isConstructor((MethodTree) tree)) { + validateTargetLocation(tree, type, TypeUseLocation.CONSTRUCTOR_RESULT); + } else { + validateTargetLocation(tree, type, TypeUseLocation.RETURN); + } break; default: type = atypeFactory.getAnnotatedType(tree); diff --git a/framework/src/main/java/org/checkerframework/common/basetype/messages.properties b/framework/src/main/java/org/checkerframework/common/basetype/messages.properties index 832a2d12a16..7b4c723904f 100644 --- a/framework/src/main/java/org/checkerframework/common/basetype/messages.properties +++ b/framework/src/main/java/org/checkerframework/common/basetype/messages.properties @@ -25,6 +25,7 @@ type.invalid=invalid type: annotations %s in type "%s" type.invalid.conflicting.annos=invalid type: conflicting annotations %s in type "%s" type.invalid.too.few.annotations=invalid type: missing annotations %s in type "%s" type.invalid.annotations.on.use=invalid type: annotations %s conflict with declaration of type %s +type.invalid.annotations.on.location=annotation %s used on prohibited locations %s type.invalid.super.wildcard=bounds must have the same annotations.%nsuper bound : %s%nextends bound: %s cast.unsafe=cast from "%s" to "%s" cannot be statically verified invariant.cast.unsafe=cannot cast from "%s" to "%s" diff --git a/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java b/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java index 61a562295f7..1bb9314a4af 100644 --- a/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java +++ b/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java @@ -338,6 +338,8 @@ // Do not perform a JRE version check. "noJreVersionCheck", + // Do not validate meta-annotation @TargetLocations + "ignoreTargetLocations", /// Format of messages // Output detailed message in simple-to-parse format, useful diff --git a/framework/src/test/java/org/checkerframework/framework/test/junit/AccumulationTest.java b/framework/src/test/java/org/checkerframework/framework/test/junit/AccumulationTest.java index 0d8b18a8789..273290e5074 100644 --- a/framework/src/test/java/org/checkerframework/framework/test/junit/AccumulationTest.java +++ b/framework/src/test/java/org/checkerframework/framework/test/junit/AccumulationTest.java @@ -17,7 +17,14 @@ public class AccumulationTest extends CheckerFrameworkPerDirectoryTest { * @param testFiles the files containing test code, which will be type-checked */ public AccumulationTest(List testFiles) { - super(testFiles, TestAccumulationChecker.class, "accumulation", "-encoding", "UTF-8"); + super( + testFiles, + TestAccumulationChecker.class, + "accumulation", + // Ignore the test suite's usage of qualifiers in illegal locations. + "-AignoreTargetLocations", + "-encoding", + "UTF-8"); } @Parameters diff --git a/framework/src/test/java/org/checkerframework/framework/test/junit/ReflectionTest.java b/framework/src/test/java/org/checkerframework/framework/test/junit/ReflectionTest.java index a902b8d41e5..6ede8662616 100644 --- a/framework/src/test/java/org/checkerframework/framework/test/junit/ReflectionTest.java +++ b/framework/src/test/java/org/checkerframework/framework/test/junit/ReflectionTest.java @@ -15,7 +15,12 @@ public class ReflectionTest extends CheckerFrameworkPerDirectoryTest { * @param testFiles the files containing test code, which will be type-checked */ public ReflectionTest(List testFiles) { - super(testFiles, ReflectionTestChecker.class, "reflection"); + super( + testFiles, + ReflectionTestChecker.class, + "reflection", + // Ignore the test suite's usage of qualifiers in illegal locations. + "-AignoreTargetLocations"); } @Parameters diff --git a/framework/src/test/java/org/checkerframework/framework/test/junit/ReturnsReceiverTest.java b/framework/src/test/java/org/checkerframework/framework/test/junit/ReturnsReceiverTest.java index ab25ec3a7a6..a4526de8246 100644 --- a/framework/src/test/java/org/checkerframework/framework/test/junit/ReturnsReceiverTest.java +++ b/framework/src/test/java/org/checkerframework/framework/test/junit/ReturnsReceiverTest.java @@ -20,7 +20,9 @@ public ReturnsReceiverTest(List testFiles) { ReturnsReceiverChecker.class, "returnsreceiver", "-Astubs=stubs/", - "-nowarn"); + "-nowarn", + // Ignore the test suite's usage of qualifiers in illegal locations. + "-AignoreTargetLocations"); } @Parameters diff --git a/framework/src/test/java/org/checkerframework/framework/test/junit/ValueIgnoreRangeOverflowTest.java b/framework/src/test/java/org/checkerframework/framework/test/junit/ValueIgnoreRangeOverflowTest.java index a08ff4d3179..afd06a04138 100644 --- a/framework/src/test/java/org/checkerframework/framework/test/junit/ValueIgnoreRangeOverflowTest.java +++ b/framework/src/test/java/org/checkerframework/framework/test/junit/ValueIgnoreRangeOverflowTest.java @@ -18,6 +18,8 @@ public ValueIgnoreRangeOverflowTest(List testFiles) { testFiles, org.checkerframework.common.value.ValueChecker.class, "value", + // Ignore the test suite's usage of qualifiers in illegal locations. + "-AignoreTargetLocations", "-A" + ValueChecker.REPORT_EVAL_WARNS, "-A" + ValueChecker.IGNORE_RANGE_OVERFLOW); } diff --git a/framework/src/test/java/org/checkerframework/framework/test/junit/ValueNonNullStringsConcatenationTest.java b/framework/src/test/java/org/checkerframework/framework/test/junit/ValueNonNullStringsConcatenationTest.java index 8f3aa0af21d..f6d75d9e364 100644 --- a/framework/src/test/java/org/checkerframework/framework/test/junit/ValueNonNullStringsConcatenationTest.java +++ b/framework/src/test/java/org/checkerframework/framework/test/junit/ValueNonNullStringsConcatenationTest.java @@ -17,6 +17,8 @@ public ValueNonNullStringsConcatenationTest(List testFiles) { testFiles, org.checkerframework.common.value.ValueChecker.class, "value-non-null-strings-concatenation", + // Ignore the test suite's usage of qualifiers in illegal locations. + "-AignoreTargetLocations", "-A" + ValueChecker.REPORT_EVAL_WARNS, "-A" + ValueChecker.NON_NULL_STRINGS_CONCATENATION); } diff --git a/framework/src/test/java/org/checkerframework/framework/test/junit/ValueTest.java b/framework/src/test/java/org/checkerframework/framework/test/junit/ValueTest.java index fe40bfa943e..f31984cc2ad 100644 --- a/framework/src/test/java/org/checkerframework/framework/test/junit/ValueTest.java +++ b/framework/src/test/java/org/checkerframework/framework/test/junit/ValueTest.java @@ -24,6 +24,8 @@ public ValueTest(List testFiles) { testFiles, org.checkerframework.common.value.ValueChecker.class, "value", + // Ignore the test suite's usage of qualifiers in illegal locations. + "-AignoreTargetLocations", "-Astubs=tests/value/minints-stub.astub:tests/value/lowercase.astub", "-A" + ValueChecker.REPORT_EVAL_WARNS); } diff --git a/framework/src/test/java/org/checkerframework/framework/test/junit/ValueUncheckedDefaultsTest.java b/framework/src/test/java/org/checkerframework/framework/test/junit/ValueUncheckedDefaultsTest.java index 3872435532b..d33bdf51dd8 100644 --- a/framework/src/test/java/org/checkerframework/framework/test/junit/ValueUncheckedDefaultsTest.java +++ b/framework/src/test/java/org/checkerframework/framework/test/junit/ValueUncheckedDefaultsTest.java @@ -18,6 +18,8 @@ public ValueUncheckedDefaultsTest(List testFiles) { testFiles, ValueChecker.class, "value", + // Ignore the test suite's usage of qualifiers in illegal locations. + "-AignoreTargetLocations", "-AuseConservativeDefaultsForUncheckedCode=btyecode", "-A" + ValueChecker.REPORT_EVAL_WARNS); } diff --git a/framework/src/test/java/org/checkerframework/framework/testchecker/compound/qual/ACCBottom.java b/framework/src/test/java/org/checkerframework/framework/testchecker/compound/qual/ACCBottom.java index 54c2de9f16c..f26f4af606f 100644 --- a/framework/src/test/java/org/checkerframework/framework/testchecker/compound/qual/ACCBottom.java +++ b/framework/src/test/java/org/checkerframework/framework/testchecker/compound/qual/ACCBottom.java @@ -9,5 +9,5 @@ @SubtypeOf({ACCTop.class}) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) public @interface ACCBottom {} diff --git a/framework/src/test/java/org/checkerframework/framework/testchecker/compound/qual/CCBottom.java b/framework/src/test/java/org/checkerframework/framework/testchecker/compound/qual/CCBottom.java index 1a1e65967a1..7567920d933 100644 --- a/framework/src/test/java/org/checkerframework/framework/testchecker/compound/qual/CCBottom.java +++ b/framework/src/test/java/org/checkerframework/framework/testchecker/compound/qual/CCBottom.java @@ -9,5 +9,5 @@ @SubtypeOf({CCTop.class}) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) public @interface CCBottom {} diff --git a/framework/src/test/java/org/checkerframework/framework/testchecker/h1h2checker/H1H2AnnotatedTypeFactory.java b/framework/src/test/java/org/checkerframework/framework/testchecker/h1h2checker/H1H2AnnotatedTypeFactory.java index a6516a053e6..e97840ffd52 100644 --- a/framework/src/test/java/org/checkerframework/framework/testchecker/h1h2checker/H1H2AnnotatedTypeFactory.java +++ b/framework/src/test/java/org/checkerframework/framework/testchecker/h1h2checker/H1H2AnnotatedTypeFactory.java @@ -12,6 +12,7 @@ import org.checkerframework.framework.testchecker.h1h2checker.quals.H1S2; import org.checkerframework.framework.testchecker.h1h2checker.quals.H1Top; import org.checkerframework.framework.testchecker.h1h2checker.quals.H2Bot; +import org.checkerframework.framework.testchecker.h1h2checker.quals.H2OnlyOnLB; import org.checkerframework.framework.testchecker.h1h2checker.quals.H2Poly; import org.checkerframework.framework.testchecker.h1h2checker.quals.H2S1; import org.checkerframework.framework.testchecker.h1h2checker.quals.H2S2; @@ -47,6 +48,7 @@ protected Set> createSupportedTypeQualifiers() { H2Bot.class, H1Poly.class, H2Poly.class, + H2OnlyOnLB.class, H1Invalid.class); } diff --git a/framework/src/test/java/org/checkerframework/framework/testchecker/h1h2checker/quals/H2Bot.java b/framework/src/test/java/org/checkerframework/framework/testchecker/h1h2checker/quals/H2Bot.java index 2acdcfe6ff9..296bf34280b 100644 --- a/framework/src/test/java/org/checkerframework/framework/testchecker/h1h2checker/quals/H2Bot.java +++ b/framework/src/test/java/org/checkerframework/framework/testchecker/h1h2checker/quals/H2Bot.java @@ -13,6 +13,6 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf({H2S1.class, H2S2.class}) +@SubtypeOf({H2S1.class, H2S2.class, H2OnlyOnLB.class}) @DefaultFor(TypeUseLocation.LOWER_BOUND) public @interface H2Bot {} diff --git a/framework/src/test/java/org/checkerframework/framework/testchecker/h1h2checker/quals/H2OnlyOnLB.java b/framework/src/test/java/org/checkerframework/framework/testchecker/h1h2checker/quals/H2OnlyOnLB.java new file mode 100644 index 00000000000..2f6daffbf55 --- /dev/null +++ b/framework/src/test/java/org/checkerframework/framework/testchecker/h1h2checker/quals/H2OnlyOnLB.java @@ -0,0 +1,18 @@ +package org.checkerframework.framework.testchecker.h1h2checker.quals; + +import org.checkerframework.framework.qual.SubtypeOf; +import org.checkerframework.framework.qual.TargetLocations; +import org.checkerframework.framework.qual.TypeUseLocation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@TargetLocations({TypeUseLocation.LOWER_BOUND}) +@SubtypeOf({H2Top.class}) +public @interface H2OnlyOnLB {} diff --git a/framework/src/test/java/org/checkerframework/framework/testchecker/h1h2checker/quals/H2S1.java b/framework/src/test/java/org/checkerframework/framework/testchecker/h1h2checker/quals/H2S1.java index 87aa66bf3f5..29276abd5ed 100644 --- a/framework/src/test/java/org/checkerframework/framework/testchecker/h1h2checker/quals/H2S1.java +++ b/framework/src/test/java/org/checkerframework/framework/testchecker/h1h2checker/quals/H2S1.java @@ -1,6 +1,8 @@ package org.checkerframework.framework.testchecker.h1h2checker.quals; import org.checkerframework.framework.qual.SubtypeOf; +import org.checkerframework.framework.qual.TargetLocations; +import org.checkerframework.framework.qual.TypeUseLocation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -11,5 +13,12 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@TargetLocations({ + TypeUseLocation.FIELD, + TypeUseLocation.LOCAL_VARIABLE, + TypeUseLocation.PARAMETER, + TypeUseLocation.RETURN, + TypeUseLocation.CONSTRUCTOR_RESULT +}) @SubtypeOf({H2Top.class}) public @interface H2S1 {} diff --git a/framework/src/test/java/org/checkerframework/framework/testchecker/nontopdefault/qual/NTDBottom.java b/framework/src/test/java/org/checkerframework/framework/testchecker/nontopdefault/qual/NTDBottom.java index 9e3bbfadc77..7f69c5fb6fe 100644 --- a/framework/src/test/java/org/checkerframework/framework/testchecker/nontopdefault/qual/NTDBottom.java +++ b/framework/src/test/java/org/checkerframework/framework/testchecker/nontopdefault/qual/NTDBottom.java @@ -14,7 +14,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @SubtypeOf({NTDMiddle.class, NTDSide.class}) @DefaultFor({TypeUseLocation.LOWER_BOUND}) public @interface NTDBottom {} diff --git a/framework/src/test/java/org/checkerframework/framework/testchecker/reflection/qual/TestReflectBottom.java b/framework/src/test/java/org/checkerframework/framework/testchecker/reflection/qual/TestReflectBottom.java index 7f7823dfafb..eb81ae99876 100644 --- a/framework/src/test/java/org/checkerframework/framework/testchecker/reflection/qual/TestReflectBottom.java +++ b/framework/src/test/java/org/checkerframework/framework/testchecker/reflection/qual/TestReflectBottom.java @@ -16,6 +16,6 @@ */ @SubtypeOf({TestReflectSibling1.class, TestReflectSibling2.class}) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) @DefaultFor(TypeUseLocation.LOWER_BOUND) public @interface TestReflectBottom {} diff --git a/framework/src/test/java/org/checkerframework/framework/testchecker/supportedquals/qual/BottomQualifier.java b/framework/src/test/java/org/checkerframework/framework/testchecker/supportedquals/qual/BottomQualifier.java index 6138eafa424..5fdd37a143f 100644 --- a/framework/src/test/java/org/checkerframework/framework/testchecker/supportedquals/qual/BottomQualifier.java +++ b/framework/src/test/java/org/checkerframework/framework/testchecker/supportedquals/qual/BottomQualifier.java @@ -9,5 +9,5 @@ @SubtypeOf({Qualifier.class}) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) public @interface BottomQualifier {} diff --git a/framework/src/test/java/org/checkerframework/framework/testchecker/testaccumulation/qual/TestAccumulationBottom.java b/framework/src/test/java/org/checkerframework/framework/testchecker/testaccumulation/qual/TestAccumulationBottom.java index 0edd4029b4b..6df1ac88fd6 100644 --- a/framework/src/test/java/org/checkerframework/framework/testchecker/testaccumulation/qual/TestAccumulationBottom.java +++ b/framework/src/test/java/org/checkerframework/framework/testchecker/testaccumulation/qual/TestAccumulationBottom.java @@ -13,5 +13,5 @@ @SubtypeOf({TestAccumulation.class, TestAccumulationPredicate.class}) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) public @interface TestAccumulationBottom {} diff --git a/framework/src/test/java/org/checkerframework/framework/testchecker/util/PatternBottomFull.java b/framework/src/test/java/org/checkerframework/framework/testchecker/util/PatternBottomFull.java index f367be64949..fd016483cea 100644 --- a/framework/src/test/java/org/checkerframework/framework/testchecker/util/PatternBottomFull.java +++ b/framework/src/test/java/org/checkerframework/framework/testchecker/util/PatternBottomFull.java @@ -9,5 +9,5 @@ @SubtypeOf({PatternA.class, PatternB.class, PatternC.class}) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@TargetLocations({TypeUseLocation.LOWER_BOUND, TypeUseLocation.UPPER_BOUND}) public @interface PatternBottomFull {} diff --git a/framework/tests/h1h2checker/EnforceTargetLocation.java b/framework/tests/h1h2checker/EnforceTargetLocation.java new file mode 100644 index 00000000000..cfcf38117ea --- /dev/null +++ b/framework/tests/h1h2checker/EnforceTargetLocation.java @@ -0,0 +1,30 @@ +import org.checkerframework.framework.testchecker.h1h2checker.quals.*; + +import java.util.List; + +// :: error: (type.invalid.annotations.on.location) +public class EnforceTargetLocation { + @H2S1 Object right; + + // :: error: (type.invalid.annotations.on.location) + @H2OnlyOnLB Object wrong; + + @H2S1 Object correctUse(@H2S1 Object p1) { + // :: warning: (cast.unsafe.constructor.invocation) + @H2S1 Object o = new @H2S1 Object(); + List l; + return o; + } + + @H2OnlyOnLB + // :: error: (type.invalid.annotations.on.location) + Object incorrect() { + // :: warning: (cast.unsafe.constructor.invocation) + // :: error: (type.invalid.annotations.on.location) + @H2OnlyOnLB Object o = new @H2OnlyOnLB Object(); + return o; + } + + // :: error: (type.invalid.annotations.on.location) + void incorrectUse2(@H2OnlyOnLB Object p1) {} +} diff --git a/framework/tests/h1h2checker/InferTypeArgsPolyChecker.java b/framework/tests/h1h2checker/InferTypeArgsPolyChecker.java index 8db3f9ca1a1..d006bab8a43 100644 --- a/framework/tests/h1h2checker/InferTypeArgsPolyChecker.java +++ b/framework/tests/h1h2checker/InferTypeArgsPolyChecker.java @@ -108,6 +108,7 @@ List methodF(List lExtF, List lSupF) { } void contextF( + // :: error: (type.invalid.annotations.on.location) List<@H1Bot @H2Bot ? extends @H1Top @H2S1 String> l1, List l2, List<@H1S1 @H2S2 ? extends @H1Top @H2Top String> l3) {