On Tue, Jun 14, 2022 at 9:17 AM Brian Goetz <brian.go...@oracle.com> wrote: > > > The val type for B2 should not exist at all > > > > So B2 is really a B3a whose value projection is encapsulated. > > > and here you lost me, .ref and .val are supposed to be projection types not > classes, at runtime there is only one class. > > > And apparently I have to say this again .... It's fine to not understand what > is being proposed. If so, ask questions, or think about it for a few days > before responding. But it's Not OK to jump to dogmatic "should not" / > "wrong" pronouncements before you understand what is being proposed. That's > just unhelpful. > > > > Summary: > > class B1 { } > value class B2 { private class val { } } > value class B3a { } > non-atomic value class B3n { } > > Value class here is clearly the star of the show; all value classes are > treated uniformly (ref-default, have a val); some value classes encapsulate > the val type; some value classes further relax the integrity requirements of > instances on the heap, to get better flattening and performance, when their > semantics don't require it. > > It's an orthogonal choice whether the default is "val is private" and "val is > public". > > > It makes B2.val a reality, but B3 has no sane default value otherwise it's a > B3, so B2.val should not exist. > > > Let me try explaining again. > > All value types have .ref and .val types. They have the properties we've > been discussing for a long time: ref types are references, and are therefore > nullable and atomic; val types are direct values, are not nullable, and are > _not necessarily_ atomic. > > We've been describing B2 classes as those with "no good default", but that > doesn't mean that they can't have a .val type. It means we *can't trust > arbitrary code to properly initialize a B2.val type.* Once initialized, > B2.val is fine, and have the benefit of greater flatness. We explored > language and VM features to ensure B2.val types are properly initialized, but > that ran into the rocks. > > But we can allow the B2 class itself to mediate access to the .val type. > This has two benefits: > > - We can get back some of the benefit of flattening B2.val types > - Uniformity > > Here are two examples of where a B2 class could safely and beneficially use > B2.val: > > value class Rational { > Rational[] harmonicSeq(int n) { > Rational.val[] rs = new Rational.val[n]; > for (int i=0; i<n; i++) > rs[i] = new Rational(1, n); > return rs; > } > } > > Here, we've made a _flat_ array of Rational.val, properly initialized it, and > returned it to the user. THe user gets the benefit of flatness, but can't > screw it up, because of the array store check. If Rational.val were illegal, > then no array of rationals could be flat.
And with Rational.val requiring atomic access, we can only flatten it if the underlying HW supports it (in this case, 2 ints fits nicely in 64bits so we're good). Larger .val's can only be flattened if marked as "non-atomic" (the B3n case). And because there's no tearing, handing out the flattened Rational.val[] is safe. Do I have that right? --Dan > > Similarly, a nestmate could take advantage of packing: > > value class Complex { > value class C3 { > Complex.val x, y, z; > > ... > } > > C3 c3(Complex x, Complex y, Complex z) { return new C3(x, y, z); } > > } > > C3 gets the benefit of full flattening, which it can do because its in the > nest; it can share the flattened instances safely with code outside the nest. > > (Access control is powerful thing.) > >