JSpecify: support generic methods
According to the JSpecify Spec, it is possible to add extends @Nullable Object to type parameters to siginify that T can be a nullable type.
Consider the following sample:
import org.jspecify.annotations.*;
@NullMarked
public class Todo {
public static <T extends @Nullable Object> T foo(NullableSupplier<T> code) {
return code.get();
}
public static void main(String[] args) {
Todo.<@Nullable Object> foo(() -> null);
}
@NullMarked
@FunctionalInterface
public interface NullableSupplier<T extends @Nullable Object> {
T get();
}
}
According to JSpecify Spec, this is valid since the call to foo in main explicitly specifies the type parameter T as nullable Object. The JSpecify Reference Checker also accepts this.
NullAway however falsly gives us the following error without JSpecifyMode:
Todo.java:13: error: [NullAway] returning @Nullable expression from method with @NonNull return type
Todo.<@Nullable Object> foo(() -> null);
^
(see http://t.uber.com/nullaway )
1 error
And this error with JSpecifyMode:
Todo.java:13: error: [NullAway] Cannot pass parameter of type NullableSupplier<@Nullable Object>, as formal parameter has type NullableSupplier<T>, which has mismatched type parameter nullability
Todo.<@Nullable Object> foo(() -> null);
^
(see http://t.uber.com/nullaway )
1 error
This issue seems similar to #660 and others, but I feel like my example gives a proper way to verify that this is a Bug and that the Bug would be resolved if my sample compiles.
Hi @beatbrot thanks for the report. We currently have no support for generic methods in JSpecify mode, only generic classes. See further details here: https://github.com/uber/NullAway/wiki/JSpecify-Support We are actively working on this and hope to have more support within the next few months. I will update this issue when something is implemented.
I'm happy to report that with the latest fixes from @haewiful the test case in this issue now passes in JSpecify mode! See #1074. Note that the test only passes with an explicit type argument at the call. I'm going to close this issue with that test, and open a new issue for supporting inference so that the type argument need not be written.