diff --git a/checker-qual/src/main/java/org/checkerframework/framework/qual/ConditionalPostconditionAnnotation.java b/checker-qual/src/main/java/org/checkerframework/framework/qual/ConditionalPostconditionAnnotation.java index 9b7feb69237..4e28a675003 100644 --- a/checker-qual/src/main/java/org/checkerframework/framework/qual/ConditionalPostconditionAnnotation.java +++ b/checker-qual/src/main/java/org/checkerframework/framework/qual/ConditionalPostconditionAnnotation.java @@ -66,7 +66,10 @@ @Target({ElementType.ANNOTATION_TYPE}) public @interface ConditionalPostconditionAnnotation { /** - * The qualifier that will be established as a postcondition. + * The qualifier that will be established as a postcondition. There is no point using the top + * qualifier, which would have no effect because every expression has the top type (and possibly + * some more refined type). Establishing more refined types is the point of a pre- or + * post-condition annotation. * *
This element is analogous to {@link EnsuresQualifierIf#qualifier()}. */ diff --git a/checker-qual/src/main/java/org/checkerframework/framework/qual/PostconditionAnnotation.java b/checker-qual/src/main/java/org/checkerframework/framework/qual/PostconditionAnnotation.java index 67bb434e848..1deebf8c53f 100644 --- a/checker-qual/src/main/java/org/checkerframework/framework/qual/PostconditionAnnotation.java +++ b/checker-qual/src/main/java/org/checkerframework/framework/qual/PostconditionAnnotation.java @@ -61,7 +61,10 @@ @Target({ElementType.ANNOTATION_TYPE}) public @interface PostconditionAnnotation { /** - * The qualifier that will be established as a postcondition. + * The qualifier that will be established as a postcondition. There is no point using the top + * qualifier, which would have no effect because every expression has the top type (and possibly + * some more refined type). Establishing more refined types is the point of a pre- or + * post-condition annotation. * *
This element is analogous to {@link EnsuresQualifier#qualifier()}. */ diff --git a/checker-qual/src/main/java/org/checkerframework/framework/qual/PreconditionAnnotation.java b/checker-qual/src/main/java/org/checkerframework/framework/qual/PreconditionAnnotation.java index 95af23ec376..f1cdec923b4 100644 --- a/checker-qual/src/main/java/org/checkerframework/framework/qual/PreconditionAnnotation.java +++ b/checker-qual/src/main/java/org/checkerframework/framework/qual/PreconditionAnnotation.java @@ -56,6 +56,15 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.ANNOTATION_TYPE}) public @interface PreconditionAnnotation { - /** The qualifier that must be established as a precondition. */ + /** + * The qualifier that must be established as a precondition. There is no point using the top + * qualifier, which would have no effect because every expression has the top type (and possibly + * some more refined type). Establishing more refined types is the point of a pre- or + * post-condition annotation. + * + *
This element is analogous to {@link RequiresQualifier#qualifier()}.
+ *
+ * @return the qualifier that must be established as a precondition
+ */
Class extends Annotation> qualifier();
}
diff --git a/checker/tests/nullness/PreconditionFieldNotInStore.java b/checker/tests/nullness/PreconditionFieldNotInStore.java
index 4c1aa59fe4c..3447cd7eb5b 100644
--- a/checker/tests/nullness/PreconditionFieldNotInStore.java
+++ b/checker/tests/nullness/PreconditionFieldNotInStore.java
@@ -11,6 +11,7 @@ class PreconditionFieldNotInStore {
@org.checkerframework.framework.qual.RequiresQualifier(
expression = {"this.filename"},
qualifier = org.checkerframework.checker.nullness.qual.Nullable.class)
+ // :: warning: (contracts.toptype)
@org.checkerframework.checker.nullness.qual.NonNull String getIndentString() {
return "indentString";
}
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 effc8dbfe12..6aca35b12a6 100644
--- a/framework/src/main/java/org/checkerframework/common/basetype/messages.properties
+++ b/framework/src/main/java/org/checkerframework/common/basetype/messages.properties
@@ -88,6 +88,7 @@ flowexpr.parse.context.not.determined=could not determine the context at '%s' wi
flowexpr.parameter.not.final=parameter %s in '%s' is not effectively final (i.e., it gets re-assigned)
contracts.precondition=precondition of %s is not satisfied.%nfound : %s%nrequired: %s
contracts.postcondition=postcondition of %s is not satisfied.%nfound : %s%nrequired: %s
+contracts.toptype=the top qualifer %s in contract annotation %s has no effect
contracts.conditional.postcondition=conditional postcondition is not satisfied when %s returns %s.%nfound : %s%nrequired: %s
contracts.conditional.postcondition.returntype=this annotation is only valid for methods with return type 'boolean'
# Same text for "override" and "methodref", but different key.
diff --git a/framework/src/main/java/org/checkerframework/framework/util/ContractsFromMethod.java b/framework/src/main/java/org/checkerframework/framework/util/ContractsFromMethod.java
index b22038222b5..1f0ac7a54e2 100644
--- a/framework/src/main/java/org/checkerframework/framework/util/ContractsFromMethod.java
+++ b/framework/src/main/java/org/checkerframework/framework/util/ContractsFromMethod.java
@@ -23,6 +23,7 @@
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.TreeUtils;
+import org.checkerframework.javacutil.TypeSystemError;
import org.plumelib.util.IPair;
/**
@@ -121,6 +122,7 @@ public Set