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

Non-null type argument is expected #530

Closed
ghost opened this issue Apr 10, 2021 · 20 comments
Closed

Non-null type argument is expected #530

ghost opened this issue Apr 10, 2021 · 20 comments

Comments

@ghost
Copy link

ghost commented Apr 10, 2021

Hi

Lately I started working with intellij and its inspections mechanism seems to be too sensitive but I want to make sure I'm not missing something. I set the following
private Cache<String, AnObject> objectsCache = null; (Initialization comes later on)

It marks both String and AnObject with a warning:

Non-null type argument is expected

What am I missing?
Thanks

@ben-manes
Copy link
Owner

ben-manes commented Apr 10, 2021

Oh I'm not sure ​(I use Eclipse). Maybe @vlsi can help explain what we should do.

In v3, we tried to better conform to the Checker Framework annotations for inspections (#337). The recommended change was use the signature Cache<K extends @NonNull Object, V extends @NonNull Object> to default the parameters and return types to being non-nullable, and then mark as null where needed (e.g. getIfPresent). Since all Java types can be nullable, this inspection should inform the analyzer whether a null is allowed as a parameter or return type. It sounds like IntelliJ is applying Kotlin's non-nullable type to Java code, which can't be expressed so then any Java type would be a warning. It seems like different understandings of the annotation and a warning that can't make sense for the Java language.

@ghost
Copy link
Author

ghost commented Apr 10, 2021

Thanks, I can suppress the warning but I usually prefer not to, unless it will really be something that can't be avoided otherwise.

@vlsi
Copy link
Contributor

vlsi commented Apr 10, 2021

@amosss , do you have a reproducer?

@ghost
Copy link
Author

ghost commented Apr 10, 2021

mmm... I opened the project in intellij and I see that warning there where I define the Cache variable. Nothing special.

@vlsi
Copy link
Contributor

vlsi commented Apr 10, 2021

Ok, AFAIK, IDEA does not support nullability annotations for generic type parameters yet.
A part of the story is that CheckerFramework is probably the only current implementation that suggests the way to annotate and verify generic types.

I guess IntelliJ team would follow up with https://github.com/jspecify/jspecify and support jspecify annotations and behavior once it is ready.


Cache<K extends @NonNull Object, V extends @NonNull Object>

For Checker Framework's default rules this declaration is the same as Cache<K extends Object, V extends Object>.
In practice, there are third-party issues when parsing bytecode with things like K extends @NonNull Object (javac might miscompile, or third-party libs might fail to parse).

That is why for now I refrain from K extends @NonNull Object and use K extends Object (see pgjdbc/pgjdbc#2010 ) even though it might be slightly less readable.

@ben-manes
Copy link
Owner

Oh, so the fix is to replace,

Cache<K extends @NonNull Object, V extends @NonNull Object>

with

Cache<K extends Object, V extends Object>

?

I hope jspecify makes progress because it seems kind of convoluted how analyzers interpret these annotations.

@vlsi
Copy link
Contributor

vlsi commented Apr 10, 2021

Oh, so the fix is to replace,

It would probably do.
At least it should be sufficient for caffeine users even though caffeine is not fully annotated.

You might want replacing all instances of extends @NonNull with extends or extends /* @NonNull */

@ben-manes
Copy link
Owner

Thanks @vlsi!

@amosss can you try the snapshot / jitpack on the fix commit and let us know if it resolves the warnings?

@ghost
Copy link
Author

ghost commented Apr 10, 2021

Because it's a "living" project, I always work against releases. Is there a way I can try the snapshot by changing the maven dependency and then set it back after trying?

@ben-manes
Copy link
Owner

Yes, I didn't mean to imply that you would switch your project over beyond a quick check.

The CI will publish a snapshot build to Sonatype's repository under the version 3.0.2-SNAPSHOT. You can add that repository locally as https://oss.sonatype.org/content/repositories/snapshots. This isn't a stable version.

jitpack.io can build on-demand from a commit hash from a public repository. That remains stable as a decent means for hot patching if one has no other choice. We have it set up to skip tests when built that way to avoid timeouts.

You should be able to use either locally, see if the warnings go away, and then revert back to a release version.

@ghost
Copy link
Author

ghost commented Apr 11, 2021

So just to make sure, is it enough to add this jar: https://oss.sonatype.org/content/repositories/snapshots/com/github/ben-manes/caffeine/caffeine/3.0.2-SNAPSHOT/caffeine-3.0.2-20210410.225425-20.jar to my project to check the warnings disappear (and then revert back)?

@ben-manes
Copy link
Owner

Yep.

@ghost
Copy link
Author

ghost commented Apr 11, 2021

Works like a charm, I reverted to 3.0.1 until this is officially released, thanks!

@ghost
Copy link
Author

ghost commented Apr 11, 2021

Maybe related?
Unboxing of 'cache.getIfPresent(key)' may produce 'NullPointerException'

@vlsi
Copy link
Contributor

vlsi commented Apr 11, 2021

   * @return the value to which the specified key is mapped, or {@code null} if this cache contains
   *         no mapping for the key

NPE is indeed possible if the key is not there.

@ghost
Copy link
Author

ghost commented Apr 11, 2021

Obviously :)
I do the following
if (cache.getIfPresent(key) == null || cache.getIfPresent(key) == 0)
Regarding the 2nd part, I get the mentioned warning. I guess this is not for you, but for intellij, my bad :)

@vlsi
Copy link
Contributor

vlsi commented Apr 11, 2021

I do the following
if (cache.getIfPresent(key) == null || cache.getIfPresent(key) == 0)

Please do not do that. The second read can indeed cause NPE.
You want to query the cache just once and store the result into a local variable.

@ghost
Copy link
Author

ghost commented Apr 11, 2021

You got a point there...

@ben-manes
Copy link
Owner

Released in 3.0.2

@ghost
Copy link
Author

ghost commented May 3, 2021

Thanks!

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

No branches or pull requests

2 participants