nullness glossary - jspecify/jspecify GitHub Wiki

The following are ordered (roughly) conceptually rather than lexically. You should reasonably be able to read it from top to bottom if that's your thing.

null: (noun) the special value represented by the null literal. Typically called "the null reference", even though it really represents the lack of a reference. When used as a noun, it conventionally appears in code font.

a null expression: (adj.) one that evaluates to null. For this usage, code font is unnecessary. An example containing both forms: "A method that doesn't accept null arguments typically throws an exception if you pass null anyway."

a nullness analyzer: an analysis program that tries to prevent null values from being dereferenced at runtime.

nullness: (discouraged: nullability, nullity) The broad topic concerning which expressions in a program might evaluate to null. "Nullity" is another fine word, just not the one we use. "Nullability" is long, and suggests a binary condition, which (as we're about to see) it's not.

the nullness of a static type: which one of the following buckets it falls into, typically derived from the presence/absence of annotations in the source code.

  1. a non-null type: one that excludes null as a value (in practice, null pollution might have occurred).
  2. a nullable type: one that includes null as a value (in practice, it might never actually happen).
  3. a type with unspecified nullness: one for which nullness information is unavailable. One of the other three nullnesses can always be assigned, but we don't know which one. The default nullness for nullness-applicable [type usages] in unannotated code. (Why aren't they just nullable?")
  4. a type with parametric nullness: a type variable that might be substituted with a nullable type argument. This is any unprojected usage of a type variable that isn't non-null-bounded. For example, in Set<E extends @Nullable Object>, the E in boolean add(E e) has parametric nullness. Warning: not to be confused with parametric type (a necessary but not sufficient condition for parametric nullness).

a null-producing augmented type: a type that is treated as including null when used as a from-type: its nullness is either nullable, or parametric with a null-producing upper bound. Antonym: non-null-producing.

a null-consuming augmented type: a type that is treated as including null when used as a to-type: its nullness is either nullable or unspecified. Antonym: non-null-consuming (in the sense of "not null-consuming", not "consumes non-null").

Summary:

nullness null-producing? null-consuming?
non-null no no
unspecified* no yes
parametric yes no
nullable yes yes

a nullable expression: an expression whose static type is null-producing. A nullable expression is unsafe to dereference. In theory, not being nullable would precisely mean that it cannot evaluate to null under any circumstances. In practice, it's neither necessary (because some cases of non-nullness can't be statically recognized) nor sufficient (because null pollution happens) for that condition. Antonym: non-null expression.

a nullable expression context: an expression context whose expected type is null-consuming. Only a nullable expression context can safely hold a nullable expression. Antonym: non-null expression context.

more/less nullable: the most useful way to order the four nullnesses is the order shown in the table above. These phrases refer to that order. (Note that there is no order that would make both columns above monotonic, so to get this ordering we treat null-producingness as the higher-order bit. This makes the ordering useful for defining the nullness of a type variable.)

The nullness of a type variable: which exactly-one of the following four classifications applies to the type variable:

  1. non-null-bounded
  2. unspecified-bounded
  3. parametric-bounded
  4. nullable-bounded

This classification depends only on the least nullable of the type variable's upper bounds: if that bound is non-null, then the type variable is non-null-bounded, and so forth.

(TODO: problem: a captured wildcard is a type variable too, and the lower bound matters: Compare Predicate<? super Object> and Predicate<? super @Nullable Object>. Think more on this.)

an intrinsically non-null type context: a type context in which a null value is linguistically impossible; null pollution cannot happen. In this position, a nullness annotation cannot communicate usable information.

  • a supertype in a class declaration
  • an enum constant declaration
  • an exception type listed after throws
  • an exception parameter type in catch (...) (technically not, but best treated as such)
  • after new or before ::new
  • in instanceof or a cast expression

a nullness-applicable type usage: as defined at @Nullable

a base type: a compile-time type as seen by the Java compiler, without any additional metadata provided by type-use annotations or otherwise tracked by a nullness analyzer. Warning: not to be confused with root type.

an augmented type: a base type plus a nullness corresponding to each of its type components including itself. Every type usage and non-void expression has a well-defined augmented type. A core function of a JSpecify-conformant nullness analyzer is to treat augmented types as though they were bona fide types.

a type projection or projected type: either a nullable projection or non-null projection, explained below. In both cases, projection is idempotent: it does not matter whether the type argument to T already included null. These have no precedent in the realm of base types.

the nullable projection of a type variable T: a type including all the values of T and the special value null ("T union null"). It doesn't matter whether T already included null or not. (For consistency we can equally well view @Nullable String as the nullable projection of String; we just usually don't need to.)

Non-null projection of a type variable T: a type including all the values of type T except null ("T minus null"). It doesn't matter whether T already included null or not.

Null-marked context: as defined at @NullMarked