Fwd: Null-Restricted and Nullable Types
Brian Goetz
brian.goetz at oracle.com
Sat Nov 23 23:42:59 UTC 2024
Received on valhalla-spec-comments.
Notes from the legislative analyst:
The author observes that nullability by default is a bad default, and
that we should retroactively reinterpret unadorned type names as if they
were null-restricted. The author also suggests changing some
long-standing policies, such as allowing the `--target` version to be
less than the `--source` version.
While the author purports this to be a mere "better syntax", this is
actually an incompatible, retroactive semantic change.
The author is compelled by the notion that "non-nullable would have been
a better default", which is unquestionably true (and borne out by
empirical efforts of annotating existing libraries.) However,
retroactively changing what "String" means would, quite literally, be
the biggest incompatible change in Java's history.
The issue that nullability by default was a bad choice, and the desire
to find an acceptable way to migrate away from this choice, is fully
understood. But we will not be discussing it for the time being,
because we simply have way too much work that isn't literally "the
biggest incompatible change every suggested for Java" to add this to our
plate at this time.
-------- Forwarded Message --------
Subject: Null-Restricted and Nullable Types
Date: Sat, 23 Nov 2024 21:03:32 +0100
From: Enno Thieleke <enno.thieleke at gmail.com>
To: valhalla-spec-comments at openjdk.org
Hello,
after seeing Brian's very good talk about project Valhalla he held at
the JVM Language Summit two months ago, I'd like to suggest a /slightly/
different syntax for null-restricted types. The motivation for it is
simple: We'll be using that syntax for 20+ years, so it should be
"nice". While this is a highly subjective thing, I think we can agree
that having to write (and read) less is preferable to more - even when
it comes to single characters.
I think the "bang" for null-restricted types is not necessary. While I
can't provide any numbers, I'm making the (bold) claim that the majority
of variable declarations across all Java source code on the planet is in
fact /meant to be/ null-restricted. So instead of writing `String!` for
"this mustn't be null" we should really be writing `String`. And when it
comes to nullables, we should be writing `String?` as suggested in
Brian's talk and just like in other languages.
The obvious question is: How can we make existing Java code compatible
when the same code suddenly changes semantically if we update to a new
Java version? I think this is where the `-source` and `-target` flags of
the compiler come into play. Let's assume Java 30 considers `String` to
be null-restricted and Java 29 doesn't.
Let's take a look at how the flags would affect what:
* `-source 30 -target 30`
`String` becomes null-restricted, `String?` becomes its nullable
pendant, bytecode would be generated with null checks and further
information on nullable where required.
* `-source 30 -target 29`
`String` becomes at least syntactically null-restricted (compile
time errors would occur within the same compiler run if used with
`null` or a nullable pendant), `String?` becomes its nullable
pendant, and bytecode /could/ be generated with backward compatible
null checks, but no information on nullable.
* `-source 29 -target 29` is as if Java 29 is used.
* `-source 29 -target 30`
`String` remains nullable (just like above) and bytecode would be
generated with information on nullable pretty much everywhere,
because nothing can be null-restricted.
But what if we compile against a library? The compiler can figure out,
by using the class file version, if parameter, return and field types
are null-restricted or not. If the class file version is for Java 29,
all types are effectively nullable. If the class file version is for
Java 30, null-restrictedness is implied (no information needs to be
present, in fact it needn't exist at all) and nullable types are
specifically marked as part of the compilation process of a class file.
This way it would be possible to use the new null-restricted types by
default, but developers can opt-out, which would make sense for a lot of
Java codebases out there in the beginning.
However, it might also be a good idea to have a special opt-in (or out)
compiler flag, instead of the `-source` flag, for making null-restricted
types the default or not, in which case the class file version can't be
used to determine null-restrictedness and I couldn't come up with a
different solution than introducing a flag in the byte code. With a
special compiler flag it would be possible to use new Java 31 and 32,
etc. `-source` levels, without ever activating the null-restricted types
by default, which would make the transition to null-restricted types
easier, because it wouldn't be "enforced".
In essence Java would give developers a choice: Stick to "legacy"
nullable types or enable null-restricted types for the entire code of a
compile process at once.
This may or may not be a naive approach to dealing with the situation,
I'm not sure, but I'd like to emphasize that your decision will set the
new syntax in stone for the foreseeable future and should therefore
prioritize good code readability, as it is crucial and in my opinion one
of the key features of the Java programming language and I hope that it
still will be in the years to come.
Thank you very much and regards
Enno
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/valhalla-spec-experts/attachments/20241123/38e7056c/attachment.htm>
More information about the valhalla-spec-experts
mailing list