RefObject and ValObject

Remi Forax forax at
Mon Apr 15 15:03:57 UTC 2019

> De: "Brian Goetz" <brian.goetz at>
> À: "Maurizio Cimadamore" <maurizio.cimadamore at>
> Cc: "valhalla-spec-experts" <valhalla-spec-experts at>
> Envoyé: Lundi 15 Avril 2019 16:38:58
> Objet: Re: RefObject and ValObject

>> Let's model the value vs. reference constraint explicitly - e.g. with 'val' and
>> 'ref' type kinds (and let's not open the can worm as to what the syntax should
>> be, whether it should be a type anno, etc.)

>> So:

>> val Object ---> accepts all values
>> ref Object ---> accepts all references
>> any Object ---> accepts all references

> We explored this sort of thing in Q world. One place where this really was
> painful was what it did to generic tvar constraints; we had an entire new
> algebra of constraints:

> <ref T extends Bound> void m(T t) { … }

val, ref and any only applies to Object. 

if you prefer in term of notation, let's rename ref Object to Object?, val Object to Object! and any Object to Object*, 

you can apply ? on any value type, Object included, 
you can apply ! and * only on Object. 

Object? is erased to Ljava/lang/Object; by the generic signature is Ljava/lang/Object/* (so it's Object for the VM and Object! for the compiler), 
Object! is erased to Qjav/lang/Object; 
Object* is erased to Ljava/lang/Object; 

As a bound of a type variable, Object is equivalent to Object? by backward compatibility. 
<T extends Object!> void m(T t) { … } 
means that T is not nullable, so it's a value type. 

And at runtime, instead of 
(o instanceof Object!) 
one will write 


> which was ad hoc and composed terribly. This hell is _exactly_ the thing that
> pushed us to Ref/ValObject as _types_ in the first place. (More of the same:
> what is “ref Object”.class, and how does it differ from “any Object”.class?).

>> 2) reinterpret `Object` as `any Object`

>> That is, the semantics of `Object` is being redefined here - code which assumed
>> to work with references might need to opt-in to additional constraints (e.g.
>> add `ref`) in order to make sure it still work as intended.

> Right. Q-world tried it the other way, and we were in utter migration hell.
> There are migration cases in this direction too, but we are convinced they are
> orders of magnitude fewer.

>> I don't see another way out of this conundrum - other than adding a special rule
>> (z2) which says that `new Object()` is treated specially and always has kind
>> `ref`. But doing so will run afoul in almost every possible way - as soon as
>> you manipulate the result of the `new` in any way (cast, assignment to variable
>> of type `Object`, ...) you go back to `any` and you are back to a place that is
>> incompatible with `ref Object`.

> Yes, this is the cost. I have to think that given a choice between some
> weirdness around ’new Object’, and dramatic, awful new kinds of types that
> complicate type uses, type descriptors, reflection, etc, etc, etc, that making
> the former work is going to be less painful, both for us and for users.

>> Your idea of treating Object as abstract is, I believe, a sound one (which
>> doesn't need any extra rule) - but we might have to figure out some story for
>> anonymous inner classes of the kind `new Object() { ... }`.

> Right. And, again, this can be treated as a migration issue, and we can start
> warning users to migrate their source now.

More information about the valhalla-spec-observers mailing list