`WarnOnGenericInferenceFailure` reports an inference failure for a `@Nullable` argument passed to a generic method of `@NullUnmarked` code

Open
#2,125 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
25/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
java
Domain
devtools

Research direction

Start with the repro in the issue: a @NullUnmarked class whose generic method Lib.id(s) receives a @Nullable argument and returns into a @NonNull location. The issue points at ConstraintSolver#addSubtypeConstraint and localVariableType as the likely reason locals are not flagged, and the WarnOnGenericInferenceFailure option gates the diagnostic. Done means deciding whether inference should be skipped for unmarked callees, then confirming that the repro is silent with the option on and that the @NullMarked case still reports. The maintainers still need to settle that design question, so this is not a good first pick.

Written by the indexing model from the issue text.

Description

(This bug report was generated by Claude Sonnet 5.5 with "high" effort. See also https://github.com/PicnicSupermarket/error-prone-support/pull/2299#issuecomment-6590316084.)

With JSpecifyExperimental, passing a @Nullable argument to a generic method of unmarked code, with the result flowing into a @NonNull location (a return, a field, or a method argument), reports an inference failure. Unmarked code is otherwise treated optimistically: it accepts null, and its return values are assumed to be non-null. A real-world example is Refaster.emitCommentBefore("REPLACEME", null) (Error Prone, <T> T emitCommentBefore(String, T)), whose result is passed to a @NullMarked method.

import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.NullUnmarked;
import org.jspecify.annotations.Nullable;

@NullMarked
class Repro2 {
  @NullUnmarked
  static class Lib {
    static <T> T id(T t) {
      throw new RuntimeException();
    }
  }

  String test(@Nullable String s) {
    return Lib.id(s);
  }
}

Options: -XepOpt:NullAway:OnlyNullMarked=true -XepOpt:NullAway:JSpecifyMode=true -XepOpt:NullAway:JSpecifyExperimental=true

Repro2.java:15: warning: [NullAway] inference failure: type variable T constrained to be both @NonNull and @Nullable
    return Lib.id(s);
                 ^

Reproduced with NullAway 0.14.3 and with master (002c08d2), Error Prone 2.51.0, JDK 25. No diagnostic is reported with -XepOpt:NullAway:WarnOnGenericInferenceFailure=false.

Observations:

  • The same failure is reported for fld = Lib.id(s); (a String field) and take(Lib.id(s)) (for static String take(String s)).
  • String result = Lib.id(s); is not reported, nor is later returning, passing or dereferencing result, nor is Lib.id(s).trim(). I presume this is because the assignment does not constrain the top-level type of a local variable (see ConstraintSolver#addSubtypeConstraint, localVariableType).
  • Nested types are still constrained for locals, so there the local is no workaround: with static <T> List<T> listOf(T t) added to Lib, List<String> result = Lib.listOf(s); is reported with the same message.
  • Passing null rather than a @Nullable variable behaves the same, as does a callee in a class outside of AnnotatedPackages rather than a @NullUnmarked one.
  • If Lib is @NullMarked, the call is reported with both this inference failure and the regular "passing @Nullable parameter" error, which seems right. For unmarked code I'd expect no diagnostic, or perhaps that inference is not attempted at all; is the current behavior intended?
Dominant language
Java
Stars
4.1k
Forks
379
Avg merge
1d 2h
Merged PRs (30d)
106

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from uber/NullAway

All issues in uber/NullAway

Similar issues

More Java issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.