jspecify: [moved to #230] Decide whether to include a `@NonNull` annotation

[edit: closed for being too long and disorganized. See #230.]

[TODO: direct link to doc about this issue]

The question was initially asked by @cpovirk

To be honest, I didn’t get the question

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 60 (2 by maintainers)

Most upvoted comments

@cpovirk maybe it’s unfair to put the burden of proof in this direction, but I (still) don’t have any intuition for how this annotation can introduce problems? I can follow the arguments for how it could be (made) largely unnecessary, but I am frankly lost as to how it could be bad to have it. Is this just about minimizing what we provide, or are there other risks here? How do those risks compare to the problems with the other options you mention as alternatives?

I can buy that per-method defaults can reduce the need for @NonNull, but per-method defaults arguably have their own downsides in terms of clarity (with and without type parameters in the mix). Further, and this is somewhat problematic / speculative to bring up, it seems plausible someone might want to just use type-use annotations in method bodies or on a field, to aid in their coding–with or without annotating method parameters/returns–and even though we don’t want to prescribe what tools should do with that, I also don’t think we’d want people to use a different set of nullness annotations in method bodies just because we’re missing one they’d like. Which also highlights another issue, which is that if we leave it out we seemingly run the risk that people try to compensate with, say, @javax.annotations.Nonnull if they feel they need it.

More philosophically, I think I’m struggling to even imagine a world without @NonNull at least in part b/c I think of @NonNull and @Nullable as the two annotations that fundamentally define the semantics, by refining the base types they’re applied to, and @DefaultNonNull as an optional shortcut/convenience. Case in point, the way I’ve tried to define @DefaultNonNull is in terms of “imagining” that @NonNull was placed in various places in its scope. Pulling @NonNull doesn’t strictly prevent that, since we can still “imagine” that it’s there, or make some other construct, but it is exceedingly odd to me to not be able to directly “address” or “say” the thing that @DefaultNonNull indirectly gets at.

The most recent comment sounds like the need for an annotation like @NonNull, even if isn’t called that, is accepted, so I propose we close this. We have issue #91 to discuss @NonNull specifically on type variables, which I believe has been the only potentially questionable use of @NonNull identified here, and since that issue motivates the different name mentioned, we can discuss it there as well.

At danger of missing something, but for my future self’s benefit, I’ll add that it seems inescapable that we need an annotation to express non-nullness of a particular type usage (whatever that annotation is called), at a minimum, for two use cases I’m aware of:

  • for “sprinkling” annotations into a file, in particular, for incremental, successive adoption. I can imagine both API owners and API consumers doing this. Without such an annotation, the only way of making anything non-null would be to add @DefaultNonNull to the entire surrounding class, which not only seems heavy-handed, but also puts substantial burden to review entire files on first-time users that may only be interested in a single method (or smaller).
  • APIs that want to make annotations as explicit as possible, as Android’s API currently does, for instance, would probably want to avoid default annotations.

I believe the first use case in particular deserves attention as it seems to affect ease of adoption: absence of @NonNull effectively appears to be an entry barrier to using nullness annotations.

(This makes me think we might get mileage from more systematically writing up use cases somewhere: doing so may help us answer other questions as well, e.g., issue #89.)

For risk of sounding like a broken record, but I cannot fancy how we could ever explain non-null types to users without @Nonnull. Not sure if I mentioned already: In Eclipse text hovers over a method affected by @NonNullByDefault will expand all signatures by inserting @NonNull whereever this is the effective annotation. The same for inferred types. If we don’t have that annotation, we cannot communicate this fact to the user – bummer.