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

JSpecify: Modify Array Type Use Annotation Syntax #850

Merged
merged 26 commits into from
Oct 25, 2023

Conversation

armughan11
Copy link
Collaborator

@armughan11 armughan11 commented Oct 18, 2023

Currently, NullAway does not support @Nullable annotations on array elements (#708). Both @Nullable String[] and String @Nullable [] are currently treated identically, and NullAway considers both annotations as the array itself might be null.

This is the first step to bring the annotation syntax in line with JSpecify norms, which treats @Nullable String[] as the array elements could be null while String @Nullable [] implies the array itself could be null.

After this change, NullAway completely ignores type-use annotations on array element types, such as @Nullable String[], and only considers type-use annotations on the top-level type, i.e., String @Nullable []. This is an intermediary change, and support for type-use annotations on array element types will be added eventually. Additionally, this only applies to JSpecify mode.

Note that for now, handling of declaration annotations is unchanged; we will very likely revisit this in the future.

Unit tests currently conform to the current behavior of NullAway after the changes and some tests have TODOs until we are able to detect the nullability of array elements.

Added Unit Tests for @nullable annotations on array in JSpecify mode and modified behaviour.
@armughan11 armughan11 changed the title Added unit tests & modify JSpecify Array Type Use Annotation behavior JSpecify: Modify Array Type Use Annotation Syntax Oct 18, 2023
@armughan11 armughan11 marked this pull request as ready for review October 19, 2023 01:04
@codecov
Copy link

codecov bot commented Oct 19, 2023

Codecov Report

All modified and coverable lines are covered by tests ✅

Comparison is base (bc94dcc) 86.90% compared to head (b6318af) 86.92%.
Report is 1 commits behind head on master.

Additional details and impacted files
@@             Coverage Diff              @@
##             master     #850      +/-   ##
============================================
+ Coverage     86.90%   86.92%   +0.02%     
- Complexity     1879     1883       +4     
============================================
  Files            74       74              
  Lines          6199     6210      +11     
  Branches       1202     1206       +4     
============================================
+ Hits           5387     5398      +11     
  Misses          405      405              
  Partials        407      407              
Files Coverage Δ
...away/src/main/java/com/uber/nullaway/NullAway.java 89.78% <100.00%> (+<0.01%) ⬆️
...c/main/java/com/uber/nullaway/NullabilityUtil.java 85.71% <100.00%> (+0.39%) ⬆️
...away/src/main/java/com/uber/nullaway/Nullness.java 85.07% <100.00%> (ø)
...ullaway/dataflow/CoreNullnessStoreInitializer.java 100.00% <100.00%> (ø)

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@msridhar
Copy link
Collaborator

This is the first step to bring the annotation syntax in line with JSpecify norms, which treats @Nullable String[] as the array itself could be null while String @Nullable [] implies the array elements could be null.

This is actually the reverse of JSpecify, right?

After this change, NullAway completely ignores annotations on type, such as @Nullable String[], and only considers, String @Nullable []. However, this is an intermediary change, and this behavior will eventually be modified to conform to JSpecify syntax.

This change is only in JSpecify mode, correct?

Copy link
Collaborator

@msridhar msridhar left a comment

Choose a reason for hiding this comment

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

Promising start! The review is incomplete, as I think there is some confusion as to what the JSpecify spec is saying about where @Nullable annotations should go on an array type. See the comments for details.

Comment on lines 330 to 332
// Currently we are ignoring @Nullable annotations on type in JSpecify mode.
// Eventually, this should return true, and array access should be handled
// elsewhere.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do we say this should eventually return true? I added some docs to the enclosing method, and I think what it is meant to do is determine whether an annotation applies to a top-level type. Given that, shouldn't this method always return false in this spot in JSpecify mode?

Copy link
Collaborator Author

@armughan11 armughan11 Oct 20, 2023

Choose a reason for hiding this comment

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

I think this and all subsequent comments are attributed to my fallacy that it works the other way around. All of these are actually working as we want them to. Will clean these up!

Comment on lines 56 to 59
" // This currently reports an error since fizz is @Nullable,",
" // but it should eventually report due to fizz[0] being @Nullable",
" // BUG: Diagnostic contains: dereferenced expression fizz is @Nullable",
" int bar = fizz[0].length();",
Copy link
Collaborator

Choose a reason for hiding this comment

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

This error is correct I think.

@armughan11
Copy link
Collaborator Author

This is the first step to bring the annotation syntax in line with JSpecify norms, which treats @Nullable String[] as the array itself could be null while String @Nullable [] implies the array elements could be null.

This is actually the reverse of JSpecify, right?

@msridhar, That's correct, I actually thought it was the other way around.
Most of my comments are because of this fallacy, that's why it's a tad confusing

@armughan11
Copy link
Collaborator Author

armughan11 commented Oct 20, 2023

This change is only in JSpecify mode, correct?

That's correct, this is the only implementation change that has been made, and it's only for JSpecify mode.

Copy link
Collaborator

@msridhar msridhar left a comment

Choose a reason for hiding this comment

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

Looking better! A few more comments

.doTest();
}

@Ignore("Array type annotations aren't supported currently.")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Rather than doing @Ignore let's put a TODO comment within the test. The test serves a useful purpose of checking that writing @Nullable String [] does not apply the annotation to the top-level type in JSpecify mode.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed

.doTest();
}

@Ignore("Array type annotations aren't supported currently.")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same comment as above about not ignoring

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed

Copy link
Collaborator

@msridhar msridhar left a comment

Choose a reason for hiding this comment

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

Mostly LGTM, just all tests need to be renamed to be consistent with the other fixes

public class NullAwayJSpecifyArrayTests extends NullAwayTestsBase {

@Test
public void arrayDimensionAnnotationDereference() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Test needs to be renamed; annotation is now on top-level type

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed!

}

@Test
public void arrayDimensionAnnotationAssignment() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

another test rename

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed!

@msridhar
Copy link
Collaborator

@lazaroclapp it'd be good if you could take a quick look at this one when you get time. Basically, with this change, in JSpecify mode, we only recognize top-level nullability annotations on array type when they are in the right place

armughan11 and others added 2 commits October 22, 2023 21:48
Co-authored-by: Manu Sridharan <msridhar@gmail.com>
Copy link
Collaborator

@msridhar msridhar left a comment

Choose a reason for hiding this comment

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

Approved with a couple more minor renames. Would still like @lazaroclapp to take a look before we land this one

armughan11 and others added 2 commits October 23, 2023 16:22
Co-authored-by: Manu Sridharan <msridhar@gmail.com>
Co-authored-by: Manu Sridharan <msridhar@gmail.com>
Copy link
Collaborator

@lazaroclapp lazaroclapp left a comment

Choose a reason for hiding this comment

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

Overall, I don't have a lot of "requires changes" level comments, but I do have a few questions :)

General question, mostly for @msridhar, because I forget context: Did we decide whether JSpecify rules apply only to type use annotations or do they apply to any annotation kind as long as we are on JSpecify mode? I remember the discussion as fairly involved and subtle, but whichever one we chose, either the title or description of this PR are wrong (title says "Type Use", description makes no mention of the distinction). @msridhar I believe we said for consistency the new rules would apply to any nullability annotation, type use or not, so long as JSpecify mode was enabled? (Otherwise it might be too confusing for devs and codebases with mixed JSpecify and javax annotations should be avoided, auto-migrated, anyways...)

I understand if this PR doesn't make all the changes needed for the above all at once, but then description should provide that context.

@msridhar
Copy link
Collaborator

General question, mostly for @msridhar, because I forget context: Did we decide whether JSpecify rules apply only to type use annotations or do they apply to any annotation kind as long as we are on JSpecify mode? I remember the discussion as fairly involved and subtle, but whichever one we chose, either the title or description of this PR are wrong (title says "Type Use", description makes no mention of the distinction). @msridhar I believe we said for consistency the new rules would apply to any nullability annotation, type use or not, so long as JSpecify mode was enabled? (Otherwise it might be too confusing for devs and codebases with mixed JSpecify and javax annotations should be avoided, auto-migrated, anyways...)

Hrm, I see the issue. I think what we wanted was that for JSpecify mode, we would only recognize top-level type annotations in the "right" place for arrays. But, I realize now that with this PR, we are only checking type use annotations. If someone writes @Nullable String [] foo where @Nullable is a declaration annotation (like from javax.annotation) I think we'll still pick it up as applying to the top-level type. (@armughan11 we should add a test for this.)

I'm not sure what we should do about this. It is very confusing that one could write @Nullable String [] foo in two different parts of a code base and have it mean different things depending on whether the imported @Nullable annotation is declaration vs type use. But, if we decided to just ignore declaration annotations on array variable declarations in JSpecify mode, the same problem would still be there. So maybe the approach of this PR is no worse than the alternative? Hrm, or maybe we should (eventually) add a NullAway warning in JSpecify mode for any use of an old-style declaration @Nullable annotation? @lazaroclapp thoughts welcome :-)

@lazaroclapp
Copy link
Collaborator

Hrm, or maybe we should (eventually) add a NullAway warning in JSpecify mode for any use of an old-style declaration @Nullable annotation? @lazaroclapp thoughts welcome :-)

I think this might end up being the safest bet. The other alternatives are: a) inconsistent semantics for @Nullable seemingly only dependent on the annotation FQN, or b) "ignored" @Nullable declaration annotations (guess not ignored per-se, they would just apply to the elements, no?).

Maybe (b) is still better, with the caveat that we really want to flag it as a problem for the developer if they have such mixed annotation types at all... (i.e. any javax... nullability annotation when running on JSpecify mode. Either way, I am fine with those semantics being outside of the scope of this PR.

Copy link
Collaborator

@lazaroclapp lazaroclapp left a comment

Choose a reason for hiding this comment

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

See comment on still probably wanting a test for @Nullable String [] fizz; fizz[1];. Other than that, I think this is fine by me for this PR and the other discussion above is more long term 😀

@msridhar msridhar enabled auto-merge (squash) October 25, 2023 22:24
@msridhar msridhar merged commit def015a into uber:master Oct 25, 2023
10 checks passed
msridhar added a commit that referenced this pull request Feb 6, 2024
This is a continuation of #850 where the behavior of `@Nullable`
annotations on the array was modified.
With this PR, the aim is to allow `@Nullable` annotations on array
contents **in JSpecify mode**, and to process these annotations when
handling _reads_ from arrays. This PR does not handle checking writes to
array elements, nor does it support reasoning about null checks on array
elements in local type refinement.

---------

Co-authored-by: Manu Sridharan <msridhar@gmail.com>
@armughan11 armughan11 deleted the jspecify-array-handling branch June 3, 2024 02:02
@armughan11 armughan11 restored the jspecify-array-handling branch June 3, 2024 02:02
@armughan11 armughan11 deleted the jspecify-array-handling branch June 3, 2024 02:04
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.

3 participants