Question about universal type variables
Kevin Bourrillion
kevinb at google.com
Wed Jul 27 18:48:22 UTC 2022
Okay, I have labored for way too long to try to discuss "are values
objects?" without ever facing universal type variables head-on. Sorry! Here
goes.
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?
~~
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.
~~
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".
Model 2: All type variables are quite simply reftypes, because reftypes are
the kind that are polymorphic. As always, a type variable will enforce
whatever restrictions it must toward the goal of preserving its
substitutability. Those restrictions are what make the type variable
"universal" and produce the behaviors (quasi-nullness) we observe. Here, a
value of type T is always a reference. Keep in mind that a generic class
might eventually be used as a template to stamp out customized classes, and
in *those* classes, your usages of T might be replaced with usages of some
actual valtype. If asked "is an `E` inside `class ArrayList<E>` an `int`?"
this model would answer, "not *per se*, but this same code might be used to
stamp out a copy of ArrayList where `E` has been changed to `int`, so code
with that in mind."
~~
I think Model 1 is close to how most developers think day-to-day, but maybe
gets us into a bit of trouble sometimes. I think Model 2 is already the
more accurate way to understand type variables, when an accurate
understanding is needed, and we will probably base several of our
JSpecify/nullness explanations on it (with care). People *will* still lean
on Model 1 day-to-day, as now, but they'd do *best* to view it as a crutch
when they do.
More to the point, maybe, I'd very, very much like to not wind up with
three kinds of types, so, my money's on Model 2 at this point.
Interestingly, Model 2 drags the notion of a "non-nullable reference type"
into the mix. And we'd like to keep a path open toward other kinds of NNRTs
in the future, that act harmoniously with these. Uh oh! But... I think that
sounds better than a future where NNRTs and universal-types both exist and
are so similar.
I have no idea how any of this aligns or doesn't with the conversations
that have already happened about UTPs.
Thoughts?
--
Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/valhalla-spec-experts/attachments/20220727/c7144958/attachment-0001.htm>
More information about the valhalla-spec-experts
mailing list