value type hygiene
john.r.rose at oracle.com
Mon May 14 23:53:31 UTC 2018
On May 14, 2018, at 4:13 PM, Remi Forax <forax at univ-mlv.fr> wrote:
> I think i prefer a declaration site annotation like @ValueBasedClass to a use site annotation ValueRef<V>.
In case it's not clear what I am proposing, I am not weighing in on language
notations, but rather on VM structures in the context of the L-world experiment:
- The L-world JVM should *not* be asked to invent two new runtime types for every VT.
- Nullable references to value types in new code should be expressed using reference types.
- In bytecodes, such nullable references can be Object or a new VT-specific interface or a mix of both.
In source code, I really don't care how nullability is expressed: annotation?
keyword? punctuation? Java 5 generic? etc.
In source code there is the *option* to use interface ValueRef<VT> to denote
"nullable ref to VT", erased to "LValueRef;" in the JVM. I think that would be a
clever use of erased static types, and a thrifty re-use of existing Java 5 language
(Surely a bespoke syntax would be more concise; that's fine, but when it boils
down to a JVM descriptor, please let it be non-nullable "LVT;" or else a reference
type like "Ljava/lang/Object;" or "Ljava/lang/ValueMumble;", not a new kind of
descriptor or an MVT-style mangled name. I am claiming we don't need that
and don't want to pay for it. Please prove me wrong, if I am wrong, by
experiment with a restricted L-world JVM running real code, and not by positing
various unlikely compatibility puzzles.)
> For me a value based class, if you want to be as compatible as possible, is a reference type (so 'L') that behave like a value type at runtime, so the JIT can see it has a value type at runtime and can unbox it at will and buffer/box it before calling a method at the horizon of the inlining blob.
> So as a library designer, i can choose to either replace a class by a real value type and it will fail if null is present or as a value based class if i value (sorry !) the backward compatibility more than the performance.
(Now I'll respond to your suggestion of notation.)
The annotation approach you suggest makes it nice and easy to sneak an
annotation next to a use of a type. That's appealing. It's also sneaky since
it slightly modifies the behavior of the problem (NPE vs. pass). The downside
of the annotation is that, unless coupled with an annotation-sensitive translation
strategy, the JVM has to mine through annotations to find out which descriptor
components are nullable and which are not. The ValueTypes attribute is our
best proposal yet for a way to pass the necessary information through to
the JVM; surely you don't expect the JVM to turn around and look at
type annotations in addition?
I prefer ValueRef<VT> as a way to express nullability (instead of a type annotation)
because it carries the same information, but all in the (static) type system.
After erasure, the JVM can inspect the descriptor directly and immediately
see whether the type is nullable or not. (ValueRef is *not* in the ValueTypes
You could also drive the translation strategy to perform surgery on descriptor
elements annotated by @ValueBasedClass. Thus, an argument or return
type of type VT with that annotation would be adjusted by the translation
strategy to descriptor Object (erased from VT-or-null) or a suitable interface
(such as ValueRef). That is an erasure, and so will disturb overloading rules
and other things.
Or we could push the annotation down into the descriptor syntax as a modifier.
That's Q-world, with its own complementary problems we are trying to avoid
by running the L-world experiment.
One problem that shows up both at JVM and language level is that any
special mechanisms we invent to grease the skids of migration will be
with us forever, even after migration is a distant memory. I'd want a
story for deprecating and removing API points that need the extra
grease of @ValueBasedClass. Eventually @ValueBasedClass itself
should be deprecated.
> Note that even if we solve the null issue when a reference type is changed to a value type and i think it's not something we should focus on, there is still the problem of the identity, so transforming a reference to a value type will never be 100% compatible.
+100. Trying to cleverly solve every last compatibility problem will
freeze us into inaction.
More information about the valhalla-spec-observers