NullableWildcard
Nullness annotations directly on wildcard types are interpreted differently by different tools

Severity
WARNING

The problem

Nullness annotations directly on wildcard types are interpreted differently by different tools. β€” unless you are using the Checker Framework.

Tool interpretations and suggested alternatives

Foo<@Nullable ?>

To the Checker Framework, this means that the type argument must be nullable. They use this in ExecutorService.

To Kotlin, this has no effect. That means that the type argument can be nullable but need not be so.

While Checker Framework users do sometimes want Foo<@Nullable ?>, we commonly see them use it in places where Foo<?> would also be correct and would be more flexible. To fully preserve Kotlin behavior, Kotlin users may wish to write β€œFoo<? extends @Nullable Object>” (unless they are within the scope of @NullMarked, in which case Foo<?> is equivalent).

The effects of that change would be:

Foo<@NonNull ?>

To the Checker Framework, this means that the type argument must be non-nullable. (See the Checker Framework docs.)

To Kotlin, this has no effect. That means that the type argument can still be nullable.

We recommend a change to Foo<? extends @NonNull Object> (or, within the scope of @NullMarked, Foo<? extends Object>).

The effects of that change would be:

JSpecify specification

The JSpecify spec says that usages of their annotations on wildcard types are unrecognized (Javadoc, spec). This specification choice is motivated by the disagreement in tool behavior discussed above.

Suppression

Suppress false positives by adding the suppression annotation @SuppressWarnings("NullableWildcard") to the enclosing element.