Checker Framework argument.type.incompatible undesired positive

814 Views Asked by At

So I'm getting this error from the nullness checker

> Task :compileJava
/Users/calebcushing/IdeaProjects/ppm/scaf/src/main/java/com/xenoterracide/scaf/PebbleTemplateProcessor.java:94: error: [argument.type.incompatible] incompatible argument for parameter obj of requireNonNull.
        var console = Objects.requireNonNull( System.console() );
                                                            ^                                     ^

this is complaining that System.console() could be null, which upon reading the javadoc is true. So I wrapped it in Objects.requireNonNull() now it's complaining that the argument to requireNonNull can't be null, which is obviously not true.

How do I tell NullnessChecker to ignore Objects.requireNonNull()? I'm fine with NPE's that are explicit, it's just the accidental ones I don't want. I believe checker already ships with a stub for this.

2

There are 2 best solutions below

6
On

Edit: The below answers were written for the original post, which had 3 unrelated questions in it. (The poster later edited the original post.) I have no clue why this answer was downvoted, since it accurately answers all 3 questions, and gives links for additional information.

Please ask one question per post.

The first one was complaining that System.console() could be null, which upon reading the javadoc is true. So I wrapped it in Objects.requireNonNull() now it's complaining that the argument to requireNonNull can't be null, which is obviously not true.

This is answered in the introduction to the Checker Framework manual.

The goal of the Nullness Checker is to warn you if your program might throw a NullPointerException. If the argument to requireNonNull() is null, then your program throws a NullPointerException. Therefore, passing null to requireNonNull() leaves your program no more correct than passing null to any other routine that might dereference it, and the Nullness Checker warns about it.

You tried to silence the warning by writing requireNonNull(). As noted above, this has no effect: the program still throws NullPointerException. Instead, it is better to correct the underlying problem. Your program should check for null and issue a user-friendly message rather than crashing -- whether the crash is in your own code or in requireNonNull().

The second one is complaining about commons-lang3 parameter not being able to take null, but its documentation says otherwise.

This is also answered in the introduction to the Checker Framework manual.

The Nullness Checker reads annotations, not English Javadoc comments. In order for the Nullness Checker to know that toBoolean() can take a null argument, its signature of toBoolean() needs to be annotated as:

boolean toBoolean(@Nullable Boolean bool)

As explained in the manual, you can write that annotation so that the Nullness Checker will use it. You can also contribute commons-lang annotations back to the community, so that others can also benefit from them.

I added SuppressWarnings, not certain why it's still happening.

You need to write @SuppressWarnings where the warning is being issued, which is on the declaration of the Application class. You wrote @SuppressWarnings on a different line of your program.

0
On

Realize I'm late to the game, but hopefully this will help others who land here after searching.

You can provide a stub file to Checker which overrides the default annotations.

For my own project, I created a new folder called checker alongside the src folder in one of my common projects, and dropped in a stub file java.util.Objects.astub with these contents:

package java.util;

import org.eclipse.jdt.annotation.Nullable;

public class Objects
{
   public static <T> T requireNonNull(@Nullable T obj, String message);
}

Then I added this to our Gradle build:

checkerFramework {
   extraJavacArgs = [
      "-Astubs=${project(':my-project').file('checker')}"
   ]
}

…where my-project is the Gradle identifier for the project containing the new folder.

Checker will now load all *.astub files in that checker folder, and use the annotations provided there instead of the defaults. You can learn more at Using Stub Classes in the Checker documentation.