Skip to content

Map.merge and other methods now always return @Nullable #7340

@cushon

Description

@cushon

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.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions