RefObject and ValObject

Maurizio Cimadamore maurizio.cimadamore at
Mon Apr 15 15:29:32 UTC 2019

Again, I was not proposing we went down there (I like RefObject, ValObject).

But... using subclassing to have a semantics discussion has issues on 
its own (e.g. should we use interfaces or classes), which I think are 
distracting at this point.

Hence my use of an alternate notation in an attempt to make problems pop 
out more clearly. But, since the notation was already used in past 
proposals, it seems like I opened a can of worms :-).

To me the important questions are:

1) TYPES - utterances of `Object` in a type positon; what do they mean? 
Do they mean VALUE or REFERENCE, or TOP-TYPE?

2) EXPRESSIONS - utterances of `Object` inside expressions such as `new 
Object()`, what do they mean, again VALUE, REFERENCE or TOP-TYPE?

For (1), I think we are all in agreement that utterances of 
Object-as-a-type means TOP-TYPE.

For (2) the proposal I saw earlier said something like, we'd like for 
`new Object` to mean REFERENCE. I think that is a siren song, and this 
issue has been addressed by Brian's proposal to deal with `new Object` 
as a migration problem. Rather than suggesting to use some static 
factory instead (which works for plain instance creation but not for 
inner class creation) I think perhaps the user code should be migrated 
to use `new RefObject` and `new RefObject() { }` instead (at least if 
people want the reference semantics). But these are minor details.

The more important fact is that, even if we make Object abstract, you 
could still make

new Object() { ... }

So there's still the issue of how that expression is interpreted. I 
think the answer has gotta be, again, TOP-TYPE (as for question (1)). So:

RefObject ro = new Object() { ... } //error


On 15/04/2019 16:03, Remi Forax wrote:
> ------------------------------------------------------------------------
>     *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) { … }
> Brian,
> 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.
> and
>   <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
>   o.getClass().isValue()
> Rémi
>     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