Question about universal type variables
Dan Smith
daniel.smith at oracle.com
Wed Jul 27 22:25:15 UTC 2022
> On Jul 27, 2022, at 11:48 AM, Kevin Bourrillion <kevinb at google.com> wrote:
>
> The main question of this email is: if T is a universal type variable, then what kind of type is that? Is it a reftype, a valtype, or something else?
>
> I can see two main options for how to answer that, which I think follow naturally from the two already-existing models for how developers might conceptualize type variables.
>
> These existing models, first:
>
> Model 1: A type variable is a mere placeholder that "will be" some other type later. When you interact with it, you're "really" interacting with the future type argument. If asked a question like "is an `E` inside `class ArrayList<E>` a `Number`?" this model would say "well, it might be or it might not be".
>
> Model 2: A type variable is a bona fide local type in its own right. It is or becomes no other type but itself. Its simple job is just to enforce whatever restrictions it needs to in order to preserve its substitutability for any type argument in-bounds. If asked the same question as above, "is an `E` inside `class ArrayList<E>` a `Number`?" this model would say "no, it is certainly not, but it does guarantee to be substitutable for `Number`, among other types."
>
> I would describe Model 2 as being close to the JLS view of the world, but in a way, Model 1 is the very illusion that Model 2 is working to create. I certainly expect the majority of developers think like Model 1 most of the time, and most of the time it's okay.
I'm not *totally* sure I grasp all the differences, but here are a couple of observations that seem to support Model 2:
- At compile time, type checking, overload resolution, etc., is performed with respect to a single type variable type, not some sort of "for all possible types..." analysis. If you invoke a method on an interface bound, you're really invoking that method of the interface, not (directly) whatever method gets implemented by an instantiation of the type variable.
- At run time, the code is executed in terms of a single runtime type (the erased bound). Specialization, a JVM concept, may allow different species to carry different "type restrictions" attached to their parameter types, but those type restrictions *add* type information, they don't *contradict* type information. If the descriptor says LObject, a type restriction might say "this is an LObject that is known to be convertible to QPoint", but it won't say "instead of an LObject, this is actually a QPoint". (I'm muddling language and JVM models here, but you get the idea: generic code is executed generically.)
More information about the valhalla-spec-observers
mailing list