My (limited) understanding is:
a) The first goal is just to enable a type parameter to accept both
reftypes and valtypes as type arguments (making it a "universal" type
parameter or UTP, and making the type variable it defines for use
inside that scope a UTV).
b) Goals to follow would do progressively more efficient things when
the type arguments are valtypes. I'd expect that optimal performance
demands dynamically generating customized versions of the class in
some manner (which I'd further expect is fair to call "templating"?).
For starters, does the above seem accurate and well-stated?
Correct. We envision two phases, like your (a) and (b), where the first
is an erasure-based, language-based system which conforms to the
behavior that the VM-based specialization would offer, allowing
specialization to be viewed as a pure optimization, rather than an
actual language feature.
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?
It is a type of indeterminate ref-ness or val-ness. This will have both
restrict some old behavior and provide some new behavior. For example:
T t = null;
will generate an unchecked warning, since we can't be sure we're not
polluting the heap with nulls. (Null pollution is a straightforward
special case of heap pollution.) On the other hand, you'll be able to
use the new derived type `T.ref`, which would mean "T if its already a
ref, or the ref companion if T is a val." This allows Map::get to be
rescued:
V.ref get(K k);
If we follow these models where they lead they seem to suggest two
different answers for my question (i.e.,"if T is a UTV, what kind of
type is that?"):
Model 1: Since the UTV type represents or "stands in for" future type
arguments which might be of either kind -- and note that it does
behave differently from any regular reftype or valtype, being sort of
quasi-nullable -- we are forced to conclude that it will be a third
kind of type, a "universal" type. So the Java type system ends up
tripartite after all. And, what is a value of this type?
* The values-are-not-objects model stammers, "you've got a class
instance for sure, but it might ambiguously be a value or a reference
to an object, and often that doesn't matter".
* The values-are-objects model stammers, "you've got an object for
sure, all you don't know is the 'placement' of the object, direct or
indirected, and often that doesn't matter".
So, note that in a generic class today, there's no way to "summon" any
value of T *except null*. You can't say `new T()` or `new T[3]` or
`T.class.newInstance()`. The values of T (except null) always come from
*outside the house*, and their T-ness is backed up by synthetic casts
(modulo heap pollution). An ArrayList<T> starts out empty, then someone
puts T's in it, at which point the ArrayList can turn around and hand
those Ts back. But it can't make any new Ts. All it needs to know is
that T is layout-compatible with the layout of the bound.