> On Jul 27, 2022, at 11:48 AM, Kevin Bourrillion <[email protected]> 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.)
