<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>