On Nov 3, 2021, at 11:34 AM, Brian Goetz <brian.go...@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.

Reply via email to