Open agentgt opened 2 months ago
Here's a relatively small test case that reproduces the problem (automatically produced by Specimin):
package io.jstach.rainbowgum;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
public sealed interface ServiceRegistry extends AutoCloseable permits DefaultServiceRegistry {
public default <T> T putIfAbsent(Class<T> type, String name, Supplier<T> supplier) {
throw new Error();
}
public default void close() {
throw new Error();
}
}
record ServiceKey(Class<?> type, String name) {
ServiceKey {
Objects.requireNonNull(type);
Objects.requireNonNull(name);
}
}
final class DefaultServiceRegistry implements ServiceRegistry {
private final Map<ServiceKey, Object> services = null;
public <T> void put(Class<T> type, String name, T service) {
throw new Error();
}
@SuppressWarnings("unchecked")
public <T> T findOrNull(Class<T> type, String name) {
throw new Error();
}
@SuppressWarnings("unchecked")
public <T> List<T> find(Class<T> type) {
throw new Error();
}
@SuppressWarnings("unchecked")
public <T> void forEach(Class<T> type, BiConsumer<String, T> consumer) {
throw new Error();
}
@SuppressWarnings("unchecked")
public <T> T putIfAbsent(Class<T> type, String name, Supplier<T> supplier) {
var t = (T) services.computeIfAbsent(new ServiceKey(type, name), k -> Objects.requireNonNull(supplier.get()));
return t;
}
public void onClose(AutoCloseable closeable) {
throw new Error();
}
public void close() {
throw new Error();
}
}
Running the Nullness Checker from CF 3.47.0 on that code produces:
(base) ➜ rainbowgum-out $CHECKERFRAMEWORK/checker/bin/javac -processor nullness **/*.java
io/jstach/rainbowgum/ServiceRegistry.java:30: error: [assignment] incompatible types in assignment.
private final Map<ServiceKey, Object> services = null;
^
found : null (NullType)
required: @Initialized @NonNull Map<@Initialized @NonNull ServiceKey, @Initialized @NonNull Object>
io/jstach/rainbowgum/ServiceRegistry.java:53: error: [argument] incompatible argument for parameter obj of Objects.requireNonNull.
var t = (T) services.computeIfAbsent(new ServiceKey(type, name), k -> Objects.requireNonNull(supplier.get()));
^
found : T extends @Initialized @Nullable Object
required: T extends @Initialized @NonNull Object
2 errors
Oh, I didn't see that the reporter had added a reproducer. @agentgt beat me to it by a few minutes :)
@kelloggm That specimin tool looks cool! Starred it for future exploring. Thanks for the link to it!
The following code the supplier is inferred as
@Nullable
when it should be@NonNull
.https://github.com/jstachio/rainbowgum/blob/c8bfceaef5e07c75c76b1d59f59ef5ba4288b8b6/core/src/main/java/io/jstach/rainbowgum/ServiceRegistry.java#L168
I will try to add an isolated reproducible example so that you don't need my entire project.
Reproducible is here:
https://github.com/agentgt/checker-issues/tree/main/checker-issue-6789