<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <font size="4"><font face="monospace">This was received on the
        spec-comments list.  My comments here: <br>
        <br>
        I'm a little mystified by this take, really.  Previously, you
        had "bucket 2" classes, which didn't even have a value
        projection; now all value classes have a value projection, but
        some have the option to encapsulate them.  But that is less
        restrictive than what we had before, so its odd to get this
        argument now?  If you don't want to restrict the value
        projection for your class, then you are free to expose it.  So
        it seems you are mostly afraid of _other_ class authors being
        too restrictive.  <br>
        <br>
        <blockquote type="cite">Yes, I know what it is supposed to
          achieve: prevent users from accidentally creating
          zero-initialized values for value-types "with no resonable
          default".</blockquote>
        <br>
        The goal is bigger than this: it is to allow class authors to
        write safe classes.  If uninitialized values are OK (as they are
        with many numerics), then that's easy.  If they are not, then
        the class has two choices: write the class as to defend against
        uninitialized values as receivers and arguments (this may be
        hard), or encapsulate the initialization of flat values to
        ensure that bad values do not escape.  Requiring the value
        projection always be public forces class authors down the first
        path, which they may not realize they need to do, and may well
        get wrong even if they try.  <br>
        <br>
        Secondarily, I think you are overestimating the downside of
        using the ref type; you probably have an outdated performance
        model that says "ref is as bad as boxing."  But the ref
        projection optimizes on the stack (parameters, returns, locals)
        almost as well as the val projection.  The major performance
        difference is in the heap.  <br>
        <br>
        Your Accumulator example is correct, but I think you are
        overestimating the novelty of the problem.  Arrays have always
        had a dynamic check; I can cast String[] to Object[] and hand
        that to you, if you try to put an Integer in it, you'll get an
        ASE.  Handing out arrays for someone else to write to should
        always specify what the bounds on those writes are; "don't write
        nulls" is novel in degree but not in concept.  <br>
        <br>
        <blockquote type="cite">3. Let the compiler treat fields of
          companion-types like final fields today, i.e. enforce
          initialization. </blockquote>
        <br>
        If this were possible to do reliably, we would have gone this
        way.  But initializing final fields today has holes where the
        null is visible to the user, such as class initialization
        circularity and receiver escape.  (And a reliable protocol is
        even harder for arrays.)  Exposing a null in this way is bad,
        but exposing the zero in this way would be worse, because now
        every user has a way to get the zero and inject it into
        unsuspecting (and unguarded) implementation code.  There is
        simply no way we can reasonably expect everyone to write
        perfectly defensive code against a threat they don't fully
        understand and believe to be vanishingly rare -- and this is a
        perfect recipe for tomorrow's security exploits.  <br>
        <br>
        <blockquote type="cite">4. Provide the users with a convenient
          API for creating arrays with all elements initialized to a
          specific value.</blockquote>
        <br>
        We explored this as well; it is a good start but ultimately not
        flexible enough to be "the solution".  If a class has no good
        default, what value should it initialize array elements to? 
        There's still no good default.  And the model of "here's a
        lambda to initialize each element" is similarly an 80%
        solution.  <br>
        <br>
        The goal here is to let people write classes that can be used
        safely.  If non-initialization is an mistake then we can make
        that mistake impossible.  That's much better than trying to
        detect and recover from that mistake.  <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>Please don't restrict access to the companion-type!</td>
          </tr>
          <tr>
            <th valign="BASELINE" nowrap="nowrap" align="RIGHT">Date: </th>
            <td>Thu, 30 Jun 2022 09:33:42 +0200</td>
          </tr>
          <tr>
            <th valign="BASELINE" nowrap="nowrap" align="RIGHT">From: </th>
            <td>Gernot Neppert <a class="moz-txt-link-rfc2396E" href="mailto:mcnepp02@googlemail.com"><mcnepp02@googlemail.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.java.net">valhalla-spec-comments@openjdk.java.net</a></td>
          </tr>
        </tbody>
      </table>
      <br>
      <br>
      
      <div dir="ltr">
        <div>I've been following the valhalla-development for a very
          long time, and have also posted quite a few comments, some of
          them raising valid concerns, some of them proving my
          ignorance.</div>
        <div><br>
        </div>
        <div>This comment hopefully falls into the first category: <br>
        </div>
        <div><br>
        </div>
        <div>My concern is that allowing access-restriction for a
          value-type's "companion-type" is a severe case of "throwing
          the baby out with the bathwater".</div>
        <div><br>
        </div>
        <div>Yes, I know what it is supposed to achieve: prevent users
          from accidentally creating zero-initialized values for
          value-types "with no resonable default".</div>
        <div><br>
        </div>
        <div>However, the proposed solution of hiding the companion-type
          will force programmers to use the reference-type even if they
          do not want to.</div>
        <div>Please have a look at the following class "Accumulator". It
          assumes that "Sample" is a value-class in the same package
          with a non-public companion-type.</div>
        <div>The Javadoc must now explicitly mention some pitfalls that
          would not be there if "Sample.val" were accessible.</div>
        <div>Especially the necessary precaution about the returned
          array-type is rather ugly, right?!</div>
        <div><br>
        </div>
        <div>public class Accumulator {</div>
        <div>   private Sample.val samples;<br>
        </div>
        <div><br>
        </div>
        <div>/**</div>
        <div>Yields the samples that were taken.<br>
        </div>
        <div>Note: the returned array is actually a "flat" array! No
          element can be null. While processing this array, do not try
          to set any of its elements to null, as that may trigger an
          ArrayStoreException!</div>
        <div>*/<br>
        </div>
        <div>public Sample[] samples() {</div>
        <div>    return samples.clone();<br>
        </div>
        <div>}<br>
        </div>
        <div>}</div>
        <div><br>
        </div>
        <div>To sum it up, my proposal is:</div>
        <div><br>
        </div>
        <div>1. Make the companion-type public always.</div>
        <div>2. When introducing value-classes, document the risks of
          having "uninitialized" values under very specific
          circumstances (uninitialized fields, flat arrays).<br>
        </div>
        <div>3. Let the compiler treat fields of companion-types like
          final fields today, i.e. enforce initialization. <br>
        </div>
        <div>4. The risk of still encountering uninitialized fields is
          really really low, and is, btw, absolutely not new.<br>
        </div>
        <div>4. Provide the users with a convenient API for creating
          arrays with all elements initialized to a specific value.</div>
        <div>5. In Java, one could possibly also use this currently
          disallowed syntax for creating initialized arrays: new
          Sample.val[20] { Sample.of("Hello") };<br>
        </div>
        <div><br>
        </div>
      </div>
    </div>
  </body>
</html>