> On Dec 1, 2021, at 4:56 PM, John Rose <john.r.r...@oracle.com> wrote:
> 
> On Dec 1, 2021, at 3:29 PM, Dan Smith <daniel.sm...@oracle.com> wrote:
>> 
>> So we went down the path of "maybe there's no need for a flag at all" in 
>> today's meeting, and it might be worth more consideration, but I convinced 
>> myself that the ACC_VALUE flag serves a useful purpose for validation and 
>> clarifying intent that can't be reproduced by a "directly/indirectly extends 
>> ValueObject" test.
>> 
>> As you suggest, though, we could mandate that ACC_VALUE implies 'implements 
>> ValueObject’.
> 
> Assuming ACC_VALUE is part of the design, there are actually four
> things we can specify, for the case when a class file has ACC_VALUE set:
> 
> A. Inject ValueObject as a direct interface, whether or not it was already 
> inherited.
> B. Inject ValueObject as a direct interface, if  it is not already inherited.
> C. Require ValueObject to be present as a direct interface, whether or not it 
> was already inherited.
> D. Require ValueObject to be present as an interface, either direct or 
> inherited.

I realize my last sentence there is ambiguous, so thanks for spelling these 
out. I meant that Dan has suggested (D), and we could consider doing so. (The 
JEP says do either A or B, it's vague about what "considered to implement" 
means.)

> A and B will look magic to reflection.

This I'm unclear on. What's the magic? Are you imagining that certain 
superinterfaces be suppressed by reflection. As I said, our intent is to *not* 
suppress anything.

> B is slightly more parsimonious and less predictable than A.

Yeah, I'm not sure what I prefer. The distinction only matters, I think, for 
reflection.

> C and D are less magic to reflection, and require a bit more “ceremony” in 
> the class file.
> D is less ceremony than C.
> Also, the D condition is a normal subtype condition, while the C condition is 
> unusual to the JVM.

The "normal subtype condition" is a big reason to prefer D over C.

> I guess I prefer C and D over A and B because of the reflection magic problem,
> and also because of Dan H’s issue (IIUC) about “where do we look for the
> metadata, if not in somebody’s constant pool?”

I'll reiterate this point:

>> the trouble with gating off less-preferred behavior in old versions is that 
>> it's still there and still must be supported. JVMs end up with two 
>> strategies instead of one. A (great strategy+ok strategy) combination is 
>> arguably *worse* than just (ok strategy) everywhere.


We haven't really eliminated these problems if we're still inferring 
IdentityObject elsewhere. We've just (slightly) reduced their footprint. At the 
expense of living with two strategies instead of one.

> Since D and C have about equal practical effect, and D is both simpler to
> specify and less ceremony, I prefer D best of all.

I'm concerned about D's separate compilation problem: implementing ValueObject 
at compile time doesn't guarantee implementing ValueObject at runtime. That 
change is not, strictly speaking, a binary compatible change, but a 
superinterface author might think they could get away with it, and the 
resulting error message seems excessively punitive: "you can't load this class 
because some superinterface changed its mind about allowing identity class 
implementations". They wanted to allow more, and ended up allowing less.

Which means, to be safe, the compiler should always redundantly implement 
ValueObject in value classes, but then a compiler might forget to do so and 
introduce a subtle bug, ...

Tolerable, but it's a rough edge of D.

Reply via email to