-
Notifications
You must be signed in to change notification settings - Fork 300
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
Treat Void formal arguments as @Nullable #613
Conversation
Pull Request Test Coverage Report for Build #880
💛 - Coveralls |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Beyond the comment below, could we add a test for assigning (Void) null
to a field? I'm not sure what to expect there (though it is a more contrived case).
" }", | ||
" @Nullable Void foo2() {", | ||
" // temporarily, we treat a Void argument type as if it was @Nullable Void", | ||
" consumeVoid((Void)null);", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the test, it seems that this change makes us treat (Void) null
as @NonNull Void
when it is a parameter, not @Nullable Void
(since here consumeVoid
's argument is @NonNull
). Am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What this is meant to change is the interpretation of a Void
formal to automatically mean @Nullable Void
. See the change to nonNullPositions
here. So, the change does make the argument to consumeVoid
implicitly @Nullable
.
It is not possible at this time to always annotate the formal as @Nullable
, because, usually, in the cases where we want to pass Void
around, the formal is of some generic type T
and what we really would want is to be able to replace <Void>
with <@Nullable Void>
, see the example in #608.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it thanks! I was thinking about the actual rather than the formal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just doing consumeVoid(null)
should also have no error right? Can we test that?
Will try, though I'd expect that to fail within this hack. If we want a more robust fix here, we might need some sort of mechanism to specify the default nullness of a type. Basically, forcing NullAway to expand Edit: As expected:
Again, if we want to handle all cases, we probably need either generics support (for the 'correct' way according to JSpecify) or types that are |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code change looks good, just a couple comments on the test
" // temporarily, we treat a Void return type as if it was @Nullable Void", | ||
" return (Void)null;", | ||
" }", | ||
" void consumeVoid(Void v) {", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a comment here indicating the formal is treated as if it were @Nullable
? I think having the comment just at the call site confused me a bit
" }", | ||
" @Nullable Void foo2() {", | ||
" // temporarily, we treat a Void argument type as if it was @Nullable Void", | ||
" consumeVoid((Void)null);", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just doing consumeVoid(null)
should also have no error right? Can we test that?
Gotcha. It's fine to punt on this for now. We could also add this test with a suppression just as documentation; up to you. |
This is a follow up on #595. See that PR for some of the soundness caveats related to method overriding and the nullability of Void in our current implementation. This does, however, avoid some otherwise awkward suppressions, as shown in #608. There are two correct ways of hadling Void: a) Having it default to `@Nullable` as a type, which requires us adding a "default nullability" for some types/classes and explictly contradicts JSpecify (jspecify/jspecify#51) b) Supporting generics, and requiring explictly annotating `@Nullable Void`. This will probably also require third-party libraries which we consider annotated (such as CF), to adopt this convention. I believe (b) is the way forward long-term, which means that, for now, this hack might be the best we can do without generics support. Once NullAway supports generics, both this change and #595 should be reverted.
639ecd9
to
7622bcd
Compare
This is a follow up on #595. See that PR for some of the soundness
caveats related to method overriding and the nullability of Void
in our current implementation.
This does, however, avoid some otherwise awkward suppressions,
as shown in #608.
There are two correct ways of handling Void:
a) Having it default to
@Nullable
as a type, which requires usadding a "default nullability" for some types/classes and explicitly
contradicts JSpecify (jspecify/jspecify#51)
b) Supporting generics, and requiring explicitly annotating
@Nullable Void
.This will probably also require third-party libraries which we consider
annotated (such as CF), to adopt this convention.
I believe (b) is the way forward long-term, which means that, for now,
this hack might be the best we can do without generics support. Once
NullAway supports generics, both this change and #595 should be reverted.