> From: "Kevin Bourrillion" <kev...@google.com>
> To: "valhalla-spec-experts" <valhalla-spec-experts@openjdk.java.net>
> Sent: Tuesday, April 26, 2022 5:12:54 AM
> Subject: We need help to migrate from bucket 1 to 2; and, the == problem

> So I want to make my class identityless. But -- whoops! -- I released it years
> ago and it has lots of usages. And though I've labeled it as "value-based", 
> any
> number of these callers are depending on its identity in some way or other.

> I'd like to put -- let's say an annotation on my class, like
> `@_FutureNonIdentityClass` or whatever, with the following effects:

> * I get a warning if I'm breaking any of the rules of identityless classes, 
> like
> if I have a non-final field.
> * Use sites get a warning if they do _anything_ identity-dependent with it 
> (==,
> identity hc, synchronization, ...?)

> This would leave me in a good position to add the real identity-forsaking
> keyword later (at which time the annotation becomes redundant and should cause
> a warning until it's removed).

> We can address all this in Error Prone, but I'm not sure it should be left to
> that, partly because a bunch of JDK value-based types need this same treatment
> themselves (apparently only the synchronization warning has been rolled out so
> far?).

> Could we get this supported in javac itself? The best thing would be to roll 
> it
> out in an even earlier release than bucket 2 types themselves... the sooner 
> the
> better (maybe we could help?).

> I think the annotation could be relegated to some one-off module so it doesn't
> pollute the beautiful jdk.base forever.

> ~~~

> One of the things this means is that people should stop using `==` on these
> value-based classes.

> And that is really really good, because what we are planning to do to `==` 
> is...
> really really bad. Don't misread me: if compatibility is sacrosanct then it is
> probably the least-bad thing we can do! But honestly, it's bad, because it's
> not a behavior that anyone ever *actually wants* -- unless they just happen to
> have no fields of reference types at all. But the fact that it does work in
> that case just makes the whole thing worse, because code like that will be a
> ticking time bomb waiting to do the wrong thing as soon as one reference-type
> field is added at any nested level below that point.

> What if we give users support for their migration path, so there *are no* 
> usages
> of `==` that need to remain compatible for these types? Then we could make 
> `==`
> *not do anything* at all for bucket-2 classes.

> This approach could save us from a lot of pain (longstanding pain and new 
> pain)
> for int and Integer and friends too.

> I think Java's historical priority of "compatibility at all costs" has been
> something of an illusion; it still leaves us high and dry when *we* want to
> adopt new features as *we* end up having to make incompatible changes to do 
> it.
> But if we always gave proper support to users' migration scenarios then we
> wouldn't always *need* the absolute compatibility at the language level.

>From my experience, there are == that are buried deeply masked as innocuous == 
>on Object. 
A simple example is assertSame() of JUnit, it is defined on Object but will 
call == on B2 if the arguments are B2. 

Any non-interprocedural analysis will miss them. Perhaps an agent that rewrite 
all acmp to use invokedynamic will be able to trap those runtime call to == and 
emit a warning with the corresponding stacktrace. 

RĂ©mi 

Reply via email to