Skip to content

Provide a checker for JSpecify annotations in unrecognized locations #1785

Closed

Description

@vlsi

JSpecify defines recognized locations for @Nullable and @NonNull and states that annotations in other locations have no meaning. The specification also encourages source-analysis tools to offer an option that reports such annotations.

Could NullAway provide a checker to diagnose these cases?

For example, a checker could report @Nullable int count = 0; because annotations on primitive type usages are unrecognized and cannot affect nullness semantics.

The diagnostic should include an Error Prone-style replacement when the intended recognized location is unambiguous:

Test.java:12: error: [JSpecifyUnrecognizedAnnotationLocation] A nullness annotation directly on a wildcard has no meaning under JSpecify.
    List<@Nullable ? extends Foo> values;
         ^
    Write the annotation on the wildcard bound instead:
    List<? extends @Nullable Foo> values;

For cases without an unambiguous replacement, the diagnostic should still show the desired valid form by recommending removal:

Test.java:8: error: [JSpecifyUnrecognizedAnnotationLocation] A nullness annotation on a primitive type has no meaning under JSpecify.
    @Nullable int count = 0;
    ^
    Remove the annotation:
    int count = 0;

This lets developers and automated refactoring agents apply the intended correction without having to infer it from the specification.

Other useful diagnostics would cover annotations on local-variable root types, receiver parameters, instanceof and pattern types, cast root types, object-creation root types, direct wildcard annotations, class declarations, type-parameter declarations, and other unrecognized declaration or type-use locations.

A source-level check seems preferable to bytecode validation, consistent with the specification’s guidance that bytecode readers may ignore annotations in unrecognized locations.

Reference: https://jspecify.dev/docs/spec/#recognized-type-use
See also:

Activity

  1. vlsi commented on Aug 30, 2026

    @vlsi
    CollaboratorAuthor

    WDYT of adding such a checker to nullaway directly?
    Frankly, I'm not sure what is the best home for it: errorprone, nullaway, or another project.

    As an end-user, I would like "activate nullaway jspecify mode", and get both errors (e.g. passing null to a non-null argument) and warnings (nullable int) at the same time.

  2. msridhar commented on Aug 30, 2026

    @msridhar
    Collaborator

    I saw @cpovirk's comment on the other issue showing that Error Prone already has checkers for many of these cases. So maybe we could build on that, complete the support there, and then document the set of checks users should enable to get this functionality?

  3. vlsi commented on Aug 30, 2026

    @vlsi
    CollaboratorAuthor

    I've created a prototype for the checker in #1787.
    I've executed the checker over NullAway code and found no ignorable annotations.
    At the same time, I've integrated the checker to validate test snippet sources, and it found ignorable annotations at

    static void param(@Nullable Wrapper<String>.Fn<String> p) {}

    The fix is a part of #1787:

    - static void param(@Nullable Wrapper<String>.Fn<String> p) {}
    + static void param(Wrapper<String>.@Nullable Fn<String> p) {}

    This is the checker identifying true bugs in NullAway's tests.

  4. msridhar commented on Sep 8, 2026

    @msridhar
    Collaborator

    Closing this as we have the checker now!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions