Fix TypedKey equals/hashCode symmetry with Key#14025
Conversation
Lulu13022002
left a comment
There was a problem hiding this comment.
I'm strongly against this, TypedKey should just not extends Key, Keyed maybe at best.
|
Agree with Lulu. It is a bit nasty, a typed key should be able to extend Key, it is identifying something via a namespace and value but the fact that a the plain key implementation considers any key with equal namespace and value equal means we should probably bite the bullet and make this keyed instead. A pretty meh equal impl of KeyImpl imo, idk if this is worth bringing up with adventure folks. |
|
Makes sense, thanks both. Agree that having TypedKey extend Keyed rather than Key is the cleaner fix instead of patching equals. That's a breaking API change and a call for you all (and possibly the adventure folks), so I'll close this and leave #13678 for that direction. Appreciate the look. |
Summary
Fixes #13678.
TypedKeyImplis a record implementingKey, but it never overridesequals/hashCode, so Java generates them from both record components and only matches anotherTypedKeyImpl. Adventure'sKeyImpl.equalscompares anyKeyby namespace + value, so equality is one-directional:That breaks the symmetry clause of
Object.equals, and the two hash differently, so aTypedKeycan go missing in aHashSet<Key>built from plain keys, andcontains/removeturn order dependent when both types are mixed.This overrides
equals/hashCodeonTypedKeyImpl:TypedKey, compare underlying key and registry key (same as before, so keys from different registries stay distinct).Key, compare namespace + value to match adventure and stay symmetric.hashCodereturns the underlying key's hash so equal keys share a hash.One tradeoff: a
TypedKeynow equals its plainKey, so twoTypedKeys with the same key but different registries stay unequal while both equal that plain key, which can break transitivity in that mixed case. That is inherent toTypedKey extends Key(Effective Java item 10). This follows the approach suggested in the issue; if you'd rather have strict transitivity, I can make equality key-only instead.Changes
TypedKeyImpl: overrideequals/hashCode.TypedKeyEqualityTestcovering symmetry, hashCode consistency, and registry distinction.