value type hygiene

Brian Goetz brian.goetz at
Fri May 11 17:07:59 UTC 2018

On 5/10/2018 4:36 PM, John Rose wrote:
> On May 10, 2018, at 11:53 AM, Brian Goetz <brian.goetz at 
> <mailto:brian.goetz at>> wrote:
>> Objection sustained.  You are right; null-hostility is not documented 
>> in VBCs.
> It *is* documented for the VBC Optional:
>> A variable whose type is {@code Optional} should
>> never itself be {@code null}; it should always point to an {@code 
>> Optional}
>> instance.
> …but not for the VBC LocalDate.  So some VBCs that are null-friendly will
> require a more nuanced migration story, since we don't want value types
> per se to be nullable.

More precisely, I think you'll find that Optional is the sole type that 
makes this claim, because the very point of Optional is to be better 
than a null sentinel.  So I think we can approximate this to "all VBCs 
are currently accidentally null-friendly."  This is the big migration 

> Options:  Make *some* value types accept null according to some ad
> hoc opt-in API, yuck.  Make a nullable type constructor available, 
> like int?,
> Optional<T>? or Optional<T>.BOX.  Or limit nullability to particular
> uses of the same type.  Or create ValueRef<T> as a workaround
> interface (no VM or language changes!).  The last two are my prefs.

On "make some of them nullable", this maps to an idea we kicked around 
which is to mark values that used to be references (@MigratedFromRef), 
and have that trigger some looser behavior at either the language or VM 
or both.  More generally, this fits into a bigger idea (not yet even a 
story) which is that if we can reify the history of a class better, we 
can provide better migration tools. (Currently, we very much have a 
"these are the classes that are" philosophy, which is understandable, 
but it makes us guess about history, which isn't great.  Code evolves.)

Nullable types are generally useful (though an enormous project, and not 
one particularly amenable to nibbling around the edges.)  This has the 
advantage that people who thought LD was nullable can just fix their 
code to say "LD?" and now everyone knows what's going on. In Q-world, LD 
and LD.BOX could map to separate type descriptors, with appropriate 
implicit conversions, which was good, but with the ValueTypes attribute, 
we lose the ability to mix and match LD and LD.BOX in one file (which is 
OK), but that means we need to either enforce uniform use (bleh) or have 
some crappy declaration like "import LD as nullable" in a place where 
the user will ignore it.

ValueRef<T> sounds like another flavor of Optional<T>, and both share 
the problem that we don't have a generics story over values yet, which 
would make it magic.

So, none of these sound like slam-dunks yet.

> My high-order concern in all of this is to reduce degrees of freedom
> in classfiles, from "every descriptor makes its own choice about nullity"
> down to "each classfile makes its decision about each type's valueness"
> backed up by "and if they don't agree, the JVM expects the user to fix
> it by recompilation or special workarounds".  This is why I'm not jumping
> at the shiny possibility of int? and String! "just by adding info to the
> descriptors"; the JVM complexity costs are large and optional for
> value types.

Understood.  We'll have to validate such moves against use cases, of 
course, but its a good ATBE position.

> More on ValueRef:
> @ForValueTypesOnly
> interface ValueRef<T extends ValueRef<T>> {
>   @CanBeFreebieDownCast
>   @SuppressWarnings("unchecked")
>   default T byValue() { return (T) this; }
> }
> Ignore the annotations for a moment.

... and the magic-ness of it.

IMO, I think one of the biases that has driven us into this corner is 
the distaste for boxes.  I think we've tried too hard to say "there are 
no boxes".  I think we should admit there are boxes, maybe ValueRef is 
spelled "Box<V>" or V.BOX (where reference types box to themselves).  
And then it has all the behavior of a heavy box, for better or worse.

More information about the valhalla-spec-observers mailing list