<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<font size="4"><font face="monospace">Received on the -comments
list. <br>
<br>
<br>
</font></font>
<div class="moz-forward-container"><br>
<br>
-------- Forwarded Message --------
<table class="moz-email-headers-table" cellspacing="0" cellpadding="0" border="0">
<tbody>
<tr>
<th valign="BASELINE" nowrap="nowrap" align="RIGHT">Subject:
</th>
<td>Value objects with no companion reference type</td>
</tr>
<tr>
<th valign="BASELINE" nowrap="nowrap" align="RIGHT">Date: </th>
<td>Tue, 20 Sep 2022 16:17:06 -0500</td>
</tr>
<tr>
<th valign="BASELINE" nowrap="nowrap" align="RIGHT">From: </th>
<td>Clement Cherlin <a class="moz-txt-link-rfc2396E" href="mailto:ccherlin@gmail.com"><ccherlin@gmail.com></a></td>
</tr>
<tr>
<th valign="BASELINE" nowrap="nowrap" align="RIGHT">To: </th>
<td><a class="moz-txt-link-abbreviated" href="mailto:valhalla-spec-comments@openjdk.org">valhalla-spec-comments@openjdk.org</a></td>
</tr>
</tbody>
</table>
<br>
<br>
Are ref-less Objects compatible with the Java language? I think
the<br>
answer may sadly be "no".<br>
<br>
Imagine OptionalValue is an interface for Optional-like types and<br>
Int128 is a 128-bit integer value type.<br>
<br>
no-ref value record NoRefOptional<T>(T item) implements
OptionalValue<T> { }<br>
<br>
new OptionalValue<Int128>[] = { new
NoRefOptional<>(new Int128(3)) };<br>
<br>
What happens? An interface-typed array is necessarily an array of<br>
references. You can't stuff a larger-than-reference-size inline
value<br>
in there without breaking the fixed-size semantics of a Java
array.<br>
<br>
Either you need a pseudo-reference which takes up the same space
as a<br>
reference and acts like a reference but isn't a reference (what is<br>
it?), or you get an ArrayStoreException because the value doesn't
fit.<br>
<br>
This will occur any time you try to store a no-ref object in a<br>
ref-typed-array of superclass or superinterface type, including
the<br>
omnipresent Object[].<br>
<br>
In order to wholly avoid the Object[] problem, no-ref values could
not<br>
be cast to Object, same as primitives. No-ref values could not be
cast<br>
to interface types, same as primitives. Client code would have to<br>
treat each one as a unique, unrelated type... same as primitives.
The<br>
only way to pass no-ref values and store them in reference
contexts<br>
would be to wrap them in heap objects, but without the possibility
of<br>
auto-boxing. In essence, to treat them as Objects, you would need
to<br>
either resort to a cumbersome generic like Optional, or manually<br>
implement a ref-mirror like Integer.<br>
<br>
Do we want that?<br>
<br>
Valhalla is finally unifying primitives with objects. No-ref
values<br>
would recreate many of the sharp edges Valhalla is sanding off of<br>
primitives. While I fully believe Java *should* have been designed<br>
from the beginning to support user-defined non-null / no-ref
objects,<br>
it wasn't. I think it's too late to shoehorn them in without
breaking<br>
changes to the language. The bedrock assumption that you can
store,<br>
pass, or return _any_ value via an "Object" or "Object[]" typed<br>
variable, parameter or method is too deeply ingrained into Java
syntax<br>
(Object... x) and libraries (map.get()) to fix at this late date.<br>
<br>
While I badly want no-ref (or at least non-nullable) value types
in<br>
Java, I don't see a way to get them without either a hard fork
(Python<br>
3 style), or making them behave in all the awkward, inconvenient
ways<br>
primitives do pre-Valhalla.<br>
<br>
I think the best we can reasonably do, given Java's pervasive<br>
ref-ness, is non-nullable value types that can be converted into<br>
special non-null refs which will often be inlined (lightweight<br>
boxing). Those have challenges of their own including array<br>
initialization, covariant arrays, and heap pollution, but I'm
hopeful<br>
those problems are solvable.<br>
<br>
You will still run into NullPointerExceptions attempting to cast
null<br>
from Object or interface types to non-null types. That problem
exists<br>
right now when unboxing a null primitive wrapper. So while it's no<br>
better, it's also no worse.<br>
<br>
I do still think .ref and .val projections as distinct types with<br>
their own .class objects and especially their own visibility
mechanics<br>
is an undesirable outcome. If there's any reasonable way to unify<br>
them, they should be unified.<br>
<br>
Cheers,<br>
<br>
Clement<br>
</div>
</body>
</html>