5

Consider a method such as ConcurrentHashMap's compute method:

public V compute(
             K key,
             BiFunction<? super K,? super V,? extends V>  remappingFunction)

I would like to annotate this for nullability checking with checker framework:

public @Nullable V compute(
             K key,
             BiFunction<? super K, ? super @Nullable V, ? extends @Nullable V> remappingFunction);

but this isn't quite right: I would like to be able to infer that it returns ? extends @NonNull V in order to avoid a null check in the case where I know the remappingFunction never returns null, e.g.:

@NonNull V value = map.compute(key, (k, v) -> {
    if (v == null) {
        return new V();
    }
    v.increment();
    return v;
});

Is it possible to express that?

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • 1
    Can you use [`@PolyNull`](https://checkerframework.org/manual/#qualifier-polymorphism) in all the places you wrote `@Nullable` in your example annotation? – mernst Jul 20 '18 at 17:41
  • @mernst that certainly seems to do the trick for tests that started failing when I added the Nullable. I'll just try running it again over everything. – Andy Turner Jul 20 '18 at 18:02
  • @mernst yep, that's what I needed. Thanks. Please post an answer. – Andy Turner Jul 20 '18 at 20:49

1 Answers1

2

The Checker Framework provides two ways to write conditional specifications, where a type depends on other values or types.

  • @PolyNull indicates that two types must be the same, but their common type could be either @NonNull or @Nullable. It looks like this will enable you to express the desired specification.
  • @EnsuresNonNullIf makes a type depend on a method's return value.

Both of these are described in section Nullness Annotations in the Checker Framework Manual.

PS: Once you have an improved specification, you can submit it as a pull request to update the annotated JDK that is shipped with the Checker Framework.

mernst
  • 7,437
  • 30
  • 45
  • Thanks. Yes, I will send you a pull request. Out of interest, is there any tooling for telling me when a marked-up class and stub both exist? (And if they have differing annotations, perhaps) – Andy Turner Jul 21 '18 at 15:12
  • Per section [Using a stub file](https://checkerframework.org/manual/#stub-using) of the manual, "Use the `-AstubWarnIfOverwritesBytecode` command-line option to get a warning whenever a stub file overwrites bytecode annotations." – mernst Jul 21 '18 at 17:46
  • [Pull request](https://github.com/typetools/checker-framework/pull/2078). – Andy Turner Jul 23 '18 at 08:00
  • Can I just clarify when that flag is meant to cause warnings? Looking at the master branch on github, [the only reference to it](https://github.com/typetools/checker-framework/blob/2da4078f0e47b7a7d73007e17ed8cf15ae31e85e/framework/src/main/java/org/checkerframework/framework/stub/StubParser.java#L758) (or, the variable set from it) seems to be in an `if (false)` block. – Andy Turner Jul 24 '18 at 15:41