We need help to migrate from bucket 1 to 2; and, the == problem
Brian Goetz
brian.goetz at oracle.com
Tue Apr 26 14:09:04 UTC 2022
How much of this is already covered by https://openjdk.java.net/jeps/390 ?
On Apr 25, 2022, at 11:12 PM, Kevin Bourrillion <kevinb at google.com<mailto:kevinb at google.com>> wrote:
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.
~~~
(Just to try to move the old overton window, what I really think we should do is go further and deprecate `==` entirely, introducing `System.identityEquals(a, b)` (or maybe `===`) which would only work for identity types. Then in time `==` could be reintroduced as a synonym for `Object.equals()` and everyone would be happy and write shiny bug-free programs.... I know this would be a large deal. Sometime I will have to write at length about just how bad the problem of identity-equality overuse/abuse has been.)
--
Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com<mailto:kevinb at google.com>
More information about the valhalla-spec-observers
mailing list