Concerns about the plan for `==`
Kevin Bourrillion
kevinb at google.com
Wed Jun 15 17:51:14 UTC 2022
What I think I understand so far:
The current plan for `==` for all bucket 2+ types (except the 8 _primitive_
types, as I still use the word) is to have it perform a fieldwise `==`
comparison: identity equality for bucket 1 fields, what it's always done
for primitive fields, and of course recurse for the rest.
If we consider that the broadest meaning of `a == b` has always been "a and
b are definitely absolutely indistinguishable no matter what", then this
plan seems to compatibly preserve that, which makes sense for purposes of
transition.
What concerns me:
It's good for transition, at least on the surface, but it's a bad long-term
outcome.
Users hunger for a shorter way to write `.equals()`, and they will think
this is it. I would not underestimate the pushback they will experience to
writing it out the long way in cases where `==` at least *seems* to do the
right thing. Because in some number of cases, it *will* do the same thing;
specifically, if you can recurse through your fields and never hit a type
that overrides equals().
This is extremely fragile. A legitimate change to one type can break these
expectations for all the types directly or indirectly depending on it, no
matter how far away.
In supporting our Java users here, there's no good stance we can take on
it: if we forbid this practice and require them to call `.equals`, we're
being overzealous. If we try to help them use it carefully, at best users
will stop seeing `Object==Object` as a code smell (as we have spent years
training them to do) and then will start misusing it even for reference
types again.
btw, why did I say it's good for transition "on the surface"? Because for
any class a user might migrate to bucket 2+, any existing calls to `==` in
the wild are extremely suspect and *should* be revisited anyway; this is no
less true here than it is for existing synchronization etc. code.
What's an alternative?:
I'm sure what I propose is flawed, but I hope the core arguments are
compelling enough to at least help me fix it.
The problem is that while we *can* retcon `==` as described above, it's not
behavior anyone really *wants*. So instead we double down on the idea that
non-primitive `==` has always been about identity and must continue to be.
That means it has to be invalid for bucket 2+ (at compile-time for the .val
type; failing later otherwise?).
This would break some usages, but again, only at sites that deserve to be
reconsidered anyway. Some bugs will get fixed in the process. And at least
it's not the language upgrade itself that breaks them, only the specific
decision to move some type to new bucket. Lastly, we don't need to break
anyone abruptly; we can roll out warnings as I proposed in the email "We
need help to migrate from bucket 1 to 2".
A non-record class that forgets to override equals() from Object even upon
migrating to bucket 2+ is also suspect. If nothing special is done, it
would fail at runtime just like any other usage of `Foo.ref==Foo.ref`, and
maybe that's fine.
Again, I'm probably missing things, maybe even big things, but I'm just
trying to start a discussion. And if this can't happen I am just searching
for a solid understanding of why.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/valhalla-spec-experts/attachments/20220615/d0810bf2/attachment-0001.htm>
More information about the valhalla-spec-experts
mailing list