<div dir="ltr"><div>I'm sympathetic to some of this. But I think I can accept the stake Brian is putting in the ground. He says: a concrete class should be empowered to provide for its own integrity, not merely count on its users to not hold it wrong. If we must preserve that, then okay, we must.</div><div><br></div><div>I worry about decision fatigue for common cases, but I'm optimistic we have a really good story here now:</div><div><br></div><div>1. First you will decide whether your class is a value class. I think this should be as simple as "do you need any of the features identity would provide?"</div><div>2. Then you will decide how much you want to expose its value companion type. Is this as simple as "does it feel worth the (nonzero) risk of bogus uninitialized instances floating around?"</div><div>3. And, if you know what you're doing, and you really need to optimize heavily, you can make it non-atomic.</div><div><br></div><div>So I disagree with the main request (always-public companion types), but I have a few comments/questions on the details.</div><div><br></div><div><br></div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Jun 30, 2022 at 7:15 AM Brian Goetz <<a href="mailto:brian.goetz@oracle.com">brian.goetz@oracle.com</a>> wrote:<br></div><div dir="ltr" class="gmail_attr"><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div><font size="4"><font face="monospace">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. </font></font></div></blockquote><div><br></div><div>It is quite rare for public APIs to exchange arrays for purposes of writing to them. It's a code smell. The safe and conscientious practice since the beginning has been to only write to arrays you created yourself. I agree with Brian that there's not much new here.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><font size="4"><font face="monospace"><blockquote type="cite">3. Let the compiler treat fields of
companion-types like final fields today, i.e. enforce
initialization. </blockquote>
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. </font></font></div></blockquote><div><br></div><div>I'd still like to understand what steps we can take to reduce the damage here, even if they're not 100% solutions.</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><font size="4"><font face="monospace"> 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. </font></font></div></blockquote><div><br></div><div>fwiw, I'll still keep pushing on offering these, if I can somehow. I think it's strange that they (create-and-fill, create-and-setAll) never got added to Arrays by now. It is very nice when the user can isolate themselves from the initialization gap.</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><font size="4"><font face="monospace">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><br>
<br>
-------- Forwarded Message --------
<table cellspacing="0" cellpadding="0" border="0">
<tbody>
<tr>
<th valign="BASELINE" nowrap align="RIGHT">Subject:
</th>
<td>Please don't restrict access to the companion-type!</td>
</tr>
<tr>
<th valign="BASELINE" nowrap align="RIGHT">Date: </th>
<td>Thu, 30 Jun 2022 09:33:42 +0200</td>
</tr>
<tr>
<th valign="BASELINE" nowrap align="RIGHT">From: </th>
<td>Gernot Neppert <a href="mailto:mcnepp02@googlemail.com" target="_blank"><mcnepp02@googlemail.com></a></td>
</tr>
<tr>
<th valign="BASELINE" nowrap align="RIGHT">To: </th>
<td><a href="mailto:valhalla-spec-comments@openjdk.java.net" target="_blank">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>
</div>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><div style="line-height:1.5em;padding-top:10px;margin-top:10px;color:rgb(85,85,85);font-family:sans-serif"><span style="border-width:2px 0px 0px;border-style:solid;border-color:rgb(213,15,37);padding-top:2px;margin-top:2px">Kevin Bourrillion |</span><span style="border-width:2px 0px 0px;border-style:solid;border-color:rgb(51,105,232);padding-top:2px;margin-top:2px"> Java Librarian |</span><span style="border-width:2px 0px 0px;border-style:solid;border-color:rgb(0,153,57);padding-top:2px;margin-top:2px"> Google, Inc. |</span><span style="border-width:2px 0px 0px;border-style:solid;border-color:rgb(238,178,17);padding-top:2px;margin-top:2px"> <a href="mailto:kevinb@google.com" target="_blank">kevinb@google.com</a></span></div></div></div></div></div></div></div></div>