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