[External] : Re: Consolidating the user model
John Rose
john.r.rose at oracle.com
Wed Nov 3 19:24:13 UTC 2021
On Nov 3, 2021, at 11:34 AM, Brian Goetz <brian.goetz at oracle.com> wrote:
>
> There's lots of great stuff on subtyping in chapters 15 and 16 of TAPL (esp 15.6, "Coercion semantics"), which might be helpful. But as a tl;dr, I would suggest treating subtyping strictly as an is-a relation within our nominal type system. By this interpretation, int <! long, and int <! Object; these are both _conversions_.
Yes, that’s good. So when someone tries to say “int <: long” or “int <: Object” our response would be “sorry, you are talking about a different idea of types”. Something like “int <: Object” is a conversion the object can do, not two ways of viewing the whole object. For us, types are about is-a, not is-a-member-of-larger-set (a disguised has-a) or can-do-a-conversion (another disguised has-a).
That does lead us to the next hard problem: Which is that a value is not a box, it has a box. And yet we want reflection (getClass specifically) not to make a distinction between those two distinct entities, but assign them the same class. Which is fine, except that Classes have grabbed some of the jobs of types.
Brainstorming here: We might be happier with a method called getRuntimeType which is allowed to return different values when applied to a box/ref of Point and a value of Point. And then we notice that Point values don’t have inheritance or super types, directly, so the method paradigm (getRuntimeType being a method) is overkill; these are all statically bound methods.
And yet, there is a strong constraint that such a method, in its statically bound form, should return the same value as the corresponding call when applied to a box (under the type Object, maybe). I don’t know how to untie this knot completely.
Brainstorming again: getRuntimeType applied to a value can (and should?) be constant folded at compile time. (Same point for getClass in fact.) When applied to a ref it cannot (usually). This makes getRuntimeType feel even less like an object method, but more like a __RuntimeTypeOf[ … ] syntax (no bikesheds were painted in the production of this statement).
I’m thinking that those few users who want to extract type mirrors from (non-null) witnesses will need to specify manually which type projection they are expecting, rather than hope that the the result they want will pop out.
Not this:
Class<Point> cp = point.getClass(); //Point
Class<Point> ci = anint.getClass(); //Integer (aka int.ref)
but this:
Class<Point> cp = point.getClass().valueType(); //Point
Class<Point> ci = anint.getClass().valueType(); //int
or else this:
Class<Point> cp = point.getClass().referenceType(); //Point.ref
Class<Point> ci = anint.getClass().referenceType(); //Integer
In other words, if the rift between Integer and Point is not completely healed, users can probably work around the problems.
More information about the valhalla-spec-observers
mailing list