Fwd: Please don't restrict access to the companion-type!
Brian Goetz
brian.goetz at oracle.com
Thu Jun 30 14:11:38 UTC 2022
This was received on the spec-comments list. My comments here:
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.
> Yes, I know what it is supposed to achieve: prevent users from
> accidentally creating zero-initialized values for value-types "with no
> resonable default".
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.
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.
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.
> 3. Let the compiler treat fields of companion-types like final fields
> today, i.e. enforce initialization.
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.
> 4. Provide the users with a convenient API for creating arrays with
> all elements initialized to a specific value.
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.
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.
-------- Forwarded Message --------
Subject: Please don't restrict access to the companion-type!
Date: Thu, 30 Jun 2022 09:33:42 +0200
From: Gernot Neppert <mcnepp02 at googlemail.com>
To: valhalla-spec-comments at openjdk.java.net
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.
This comment hopefully falls into the first category:
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".
Yes, I know what it is supposed to achieve: prevent users from
accidentally creating zero-initialized values for value-types "with no
resonable default".
However, the proposed solution of hiding the companion-type will force
programmers to use the reference-type even if they do not want to.
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.
The Javadoc must now explicitly mention some pitfalls that would not be
there if "Sample.val" were accessible.
Especially the necessary precaution about the returned array-type is
rather ugly, right?!
public class Accumulator {
private Sample.val samples;
/**
Yields the samples that were taken.
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!
*/
public Sample[] samples() {
return samples.clone();
}
}
To sum it up, my proposal is:
1. Make the companion-type public always.
2. When introducing value-classes, document the risks of having
"uninitialized" values under very specific circumstances (uninitialized
fields, flat arrays).
3. Let the compiler treat fields of companion-types like final fields
today, i.e. enforce initialization.
4. The risk of still encountering uninitialized fields is really really
low, and is, btw, absolutely not new.
4. Provide the users with a convenient API for creating arrays with all
elements initialized to a specific value.
5. In Java, one could possibly also use this currently disallowed syntax
for creating initialized arrays: new Sample.val[20] { Sample.of("Hello") };
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/valhalla-spec-observers/attachments/20220630/c3d512dd/attachment-0001.htm>
More information about the valhalla-spec-observers
mailing list