? super wildcard capture conversion and null-inclusiveness rule

28 views
Skip to first unread message

Dariusz Jedrzejczyk

unread,
Dec 3, 2025, 3:53:50 PM (3 days ago) Dec 3
to jspecify-discuss
Hi,

I would like to raise a question about ? super T where the generic parameter T is @NullMarked (therefore @NonNull) and the null-inclusiveness rule.

Do I understand correctly, that in a @NullMarked package, the following code should not issue any checker warning?

    class A<V> {
        void onSuccess(Consumer<? super V> consumer) {
            consumer.accept(null);
        }
    }

And the below usage:

        A<String> a = new A<>();
        a.onSuccess(v -> System.out.println("Got v = " + v.toString()));

is expected to warn about v possibly being null (and clearly to throw an NPE at runtime)?

The actual context of the question is that a similar API exists in reactor-core and I would like to best understand how it should be modelled (to be able to pass null to the Consumer) if any of the above assumptions that I have are incorrect.

Thank you in advance for the guidance!

Best regards,
Dariusz Jędrzejczyk

Manu Sridharan

unread,
Dec 4, 2025, 10:58:55 AM (3 days ago) Dec 4
to Dariusz Jedrzejczyk, jspecify-discuss
Hi Dariusz,

I’m not an expert on wildcards, but this regular Java code does not type check:

class Test {
 void test(Consumer<? super String> consumer) {
   consumer.accept(new Object());
 }
}

This is because you can pass in a Consumer<String> to test, and that Consumer wouldn’t be able to accept an Object argument.

By similar reasoning, I don’t think your A<V> class should type-check, since for an A<String>, one could legally pass in a Consumer<String>, which cannot accept null as an argument.  

As to your example API, should the Consumer argument always be prepared to accept null as an argument?  If so, maybe you want to write Consumer<? super @Nullable T>?

Best,
Manu 

--
You received this message because you are subscribed to the Google Groups "jspecify-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jspecify-discu...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/jspecify-discuss/567503f9-5141-4d00-9ce2-963ea1362d5dn%40googlegroups.com.

Kevin Bourrillion

unread,
Dec 4, 2025, 5:52:22 PM (2 days ago) Dec 4
to Dariusz Jedrzejczyk, jspecify-discuss
Here's my reasoning: `onSuccess` wants a consumer that it can push a `null` into. In real life, I assume it might push a real `V` in some circumstances too. That means the type it wants to push is `@Nullable V`. So Manu is right, the parameter type should be `Consumer<? super @Nullable V>`. I believe the call to `consumer.accept(null)` should be generating a finding until you make that change.

In theory, that same change should affect the use-site too, by causing a checker to start inferring `v` as `@Nullable String` instead of just `String`, which would consequently lead to a finding where `v` is dereferenced. Inference is complicated, so maybe there are technical limitations, but that's at least the ideal.

(Manu, does NullAway work like this?)



Manu Sridharan

unread,
Dec 4, 2025, 7:09:43 PM (2 days ago) Dec 4
to Kevin Bourrillion, jspecify-discuss, Dariusz Jedrzejczyk
(Manu, does NullAway work like this?)

Sadly, NullAway still has basically no proper support for wildcards or for checking of generic code.  We’re starting to work on it, probably with wildcards first.  For testing with a tool probably EISOP or IntelliJ (or the reference checker!) have more complete support for those features right now.

In theory, that same change should affect the use-site too, by causing a checker to start inferring `v` as `@Nullable String` instead of just `String`, which would consequently lead to a finding where `v` is dereferenced. Inference is complicated, so maybe there are technical limitations, but that's at least the ideal.

Yes, this is what I would expect as well.  I just checked and the reference checker does report a warning at the use site when `? super @Nullable V` is used.

Best,
Manu


Dariusz Jedrzejczyk

unread,
Dec 5, 2025, 9:24:10 AM (2 days ago) Dec 5
to jspecify-discuss
Thank you, your feedback is much appreciated.
I think I was driven into the wrong conclusions by the lack of warnings when null was passed to the Consumer<? super T>.
I have refined the API to accept Consumer<? super @Nullable T> as suggested.

Best,
Dariusz
Reply all
Reply to author
Forward
0 new messages