Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Array creation annotation checks #928

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

thisisalexandercook
Copy link
Collaborator

@thisisalexandercook thisisalexandercook commented Sep 30, 2024

fixes #927 , added a warning if the first dimension (element type) of array creation is annotated with nullable. Warning will inform user that this annotation has been ignored. Also added a new error message to support the warning.

@Ao-senXiong
Copy link
Member

@thisisalexandercook Please also add test case to show the the check is implemented correctly.

TreeUtils.annotationsFromArrayCreation(tree, 0);
if (AnnotationUtils.containsSame(annotations, NULLABLE)) {
checker.reportWarning(tree, "new.array.nullable.ignored");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use this error message?
new.array.type.invalid=annotations %s may not be applied as component type for array "%s"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, because it is not about the component type.

@wmdietl wmdietl changed the title Array element nullable annotation warning Array creation annotation checks Oct 2, 2024
Copy link
Member

@wmdietl wmdietl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also look at checker/src/main/java/org/checkerframework/checker/nullness/NullnessNoInitAnnotatedTypeFactory.java and see why visitNewArray and visitNewClass are slightly different? Is there a reason one doesn't call super?

In a separate PR, can you also look at why we backed out fb6cb61 12 years ago? Why doesn't the simpler check work?

Comment on lines 351 to 353
List<? extends AnnotationMirror> annotations =
TreeUtils.annotationsFromArrayCreation(tree, 0);
if (AnnotationUtils.containsSame(annotations, NULLABLE)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
List<? extends AnnotationMirror> annotations =
TreeUtils.annotationsFromArrayCreation(tree, 0);
if (AnnotationUtils.containsSame(annotations, NULLABLE)) {
if (type.hasAnnotation(NULLABLE)) {

type is the type of the NewArrayTree, so wouldn't this perform the check you want?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about @PolyNull? Is that allowed? MonotonicNonNull?
Are some of these checks maybe in isValid?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type is holding what the annotation defaulted to (i.e. @NonNull) and I couldn't find a utility to retrieve the original @Nullable annotation (i.e. getExplicitonAnnotation() does not hold onto it), so I pull the annotations directly from the 0th dim of the tree.

Thanks for bringing up @PolyNull and @MonotonicNonNull, both suggest possible nullness so I think they should be disallowed.

@@ -22,6 +22,7 @@ nulltest.redundant=redundant test against null; "%s" is non-null
instanceof.nullable=instanceof is only true for a non-null expression
instanceof.nonnull.redundant=redundant @NonNull annotation on instanceof
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we have a similar warning for object and array creations?
On the other hand, there is the -AwarnRedundantAnnotations option... so should we remove the special case for instanceof? If needed, please file a new issue for this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense to move instanceof.nonnull.redundant to an -AwarnRedundantAnnotations flagged warning. When testing this flag I also noticed redundancy on enum isn't under this option either but is noted to be in testcase below. Will file an issue to move both of these and also do a check it see if there are any others.

enum InnerEnum {
// TODO :: warning: (redundant.anno)
// :: error: (nullness.on.enum)
@NonNull EXPLICIT,
IMPLICIT,
}

TreeUtils.annotationsFromArrayCreation(tree, 0);
if (AnnotationUtils.containsSame(annotations, NULLABLE)) {
checker.reportWarning(tree, "new.array.nullable.ignored");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, because it is not about the component type.

@thisisalexandercook
Copy link
Collaborator Author

Can you also look at checker/src/main/java/org/checkerframework/checker/nullness/NullnessNoInitAnnotatedTypeFactory.java and see why visitNewArray and visitNewClass are slightly different? Is there a reason one doesn't call super?

visitNewArray overrides a method in the PropagationTreeAnnotator class that looks at context and ensures consistent annotation on component types, whereas visitNewClass overrides the default method from SimpleTreeVisitor as it doesn't have a propagation method, so calling super here wouldn't do much.

Copy link
Member

@wmdietl wmdietl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Let's discuss the error key some more.
Also, please add a changelog entry and see whether a note somewhere in the manual would be good.

Comment on lines +25 to 27
new.array.nullable.ignored=array type annotation must be non-null
new.class.type.invalid=the annotations %s do not need be applied in object creations
nullness.on.constructor=do not write nullness annotations on a constructor, whose result is always non-null
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
new.array.nullable.ignored=array type annotation must be non-null
new.class.type.invalid=the annotations %s do not need be applied in object creations
nullness.on.constructor=do not write nullness annotations on a constructor, whose result is always non-null
new.class.type.invalid=the annotations %s do not need be applied in object creations
nullness.on.constructor=do not write nullness annotations on a constructor, whose result is always non-null
nullness.on.new.array=do not write nullness annotations on an array creation, which is always non-null

What do you think of using this key? It would follow the existing nullness.on errors.
All of these should be split into the invalid use of @Nullable and the redundant use of @NonNull #966.

An alternative would be to go with the earlier suggestion of new.array.type.invalid and split that up/reword to allow errors on the created object or the component type.
In general, it would probably have been nicer to consistently use xxx.type.invalid for all of these...

The new ignored category I don't like so much - we should just raise an error for the misuse of @Nullable and not ignore it.

@@ -349,6 +349,13 @@ public Void visitNewArray(NewArrayTree tree, Void p) {
type.toString());
}

List<? extends AnnotationMirror> annotations =
TreeUtils.annotationsFromArrayCreation(tree, 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a comment why this doesn't use type? That is already the type of the array creation. Was it because @PolyNull would already be substituted?

if (AnnotationUtils.containsSame(annotations, NULLABLE)
|| AnnotationUtils.containsSame(annotations, MONOTONIC_NONNULL)
|| AnnotationUtils.containsSame(annotations, POLYNULL)) {
checker.reportWarning(tree, "new.array.nullable.ignored");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
checker.reportWarning(tree, "new.array.nullable.ignored");
checker.reportError(tree, "new.array.nullable.ignored");

Related to the discussion of the error key, the other nullness.on messages are errors.

@@ -0,0 +1,8 @@
import org.checkerframework.checker.nullness.qual.Nullable;

public class ArrayMainModifierNullableAnnotation {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would probably put the two test cases into one file and name it ArrayCreation or something like that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Array creation is intrinsically non-null
3 participants