-
Notifications
You must be signed in to change notification settings - Fork 425
Description
In version 3.49.3, Map.merge, Map.compute, and Map.computeIfAbsent used @PolyNull in their signatures. This gave them a non-null return type when they were used with functions that operated on non-null types. That allowed code like this:
class MapMerge {
Integer doMerge(java.util.Map<String, Integer> m) {
return m.merge("", 1, Integer::sum);
}
}When we upgrade to version 3.49.4, we see the new Map signatures from #7082 / typetools/jdk#227. Those signatures use @Nullable instead of @PolyNull. That leads to a number of new errors in our codebase on code that we believe is safe. Here is a minimized example:
checker-framework-3.49.4 $ checker/bin/javac -processor nullness MapMerge.java
MapMerge.java:3: error: [return] incompatible types in return.
return m.merge("", 1, Integer::sum);
^
type of expression: @Initialized @Nullable Integer
method return type: @Initialized @NonNull Integer
1 error
There is currently a tradeoff between fixing #7082 and keeping the above code working.
But it may be possible for the checker to support both callers: The problem in #7082 might also be possible to fix by keeping the old Map signatures but changing the algorithm for type inference: The checker accepts the code from #7082 if we explicitly cast the MyFunction::mergeFunction method reference to the type (BiFunction<Integer, Integer, @Nullable Integer>).
(There was a previous report of type-inference problems with @PolyNull back in #2429. But that one looks to be fixed in recent versions, so this issue is separate.)