-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Mix in the productPrefix
hash statically in case class hashCode
#11023
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The attemt to keep Not sure if that's a big issue... |
src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
Outdated
Show resolved
Hide resolved
classOf[C].getName
instead of productPrefix
in case hashCode
productPrefix
hash statically in case class hashCode
11b1efa
to
37a12ba
Compare
2ea7949
to
dedfce3
Compare
Since 2.13, case class `hashCode` mixes in the hash code of the `productPrefix` string. This is inconsistent with the `equals` method, subclasses of case classes that override `productPrefix` compare equal but have a different `hashCode`. This commit changes `hashCode` to mix in the `productPrefix.hashCode` statically instead of invoking `productPrefix` at runtime. For case classes without primitive fields, the synthetic `hashCode` invokes `ScalaRunTime._hashCode`, which mixes in the result of `productPrefix`. To fix that, the synthetic hashCode is changed to invoke `MurmurHash3.productHash` directly and mix in the name to the seed statically. This works out with keeping `productHash` forwards and backwards compatible. The `MurmurHash3.productHash` method is deprecated / renamed to `caseClassHash`. This method computes the same hash as the synthetic `hashCode`, except for the corner case where a case class (or a subclass) override the `productPrefix`. In this case, the case class name needs to be passed manually to `caseClassHash`.
} else { | ||
if (arr == 0) | ||
if (!ignorePrefix) x.productPrefix.hashCode else seed | ||
else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rare case where I would retain extra braces (Scala 2)
@@ -152,10 +152,16 @@ object ScalaRunTime { | |||
// More background at ticket #2318. | |||
def ensureAccessible(m: JMethod): JMethod = scala.reflect.ensureAccessible(m) | |||
|
|||
// This is called by the synthetic case class `toString` method. | |||
// It originally had a `CaseClass` parameter type which was changed to `Product`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"originally" here means like first verse of Genesis
…22865) Since 2.13, case class `hashCode` mixes in the hash code of the `productPrefix` string. This is inconsistent with the `equals` method, subclasses of case classes that override `productPrefix` compare equal but have a different `hashCode` (scala/bug#13033). This commit changes `hashCode` to mix in the `productPrefix.hashCode` statically instead of invoking `productPrefix` at runtime. For case classes without primitive fields, the synthetic `hashCode` invokes `ScalaRunTime._hashCode`, which mixes in the result of `productPrefix`. To fix that, the synthetic hashCode is changed to invoke `MurmurHash3.productHash` directly and mix in the name to the seed statically. Scala 3 forward port of scala/scala#11023
Mix in the `productPrefix` hash statically in case class `hashCode`
Mix in the `productPrefix` hash statically in case class `hashCode`
Since 2.13, case class
hashCode
mixes in the hash code of theproductPrefix
string. This is inconsistent with theequals
method, subclasses of case classes that overrideproductPrefix
compare equal but have a differenthashCode
.This commit changes
hashCode
to mix in theproductPrefix.hashCode
statically instead of invokingproductPrefix
at runtime.For case classes without primitive fields, the synthetic
hashCode
invokesScalaRunTime._hashCode
, which mixes in the result ofproductPrefix
. To fix that, the synthetic hashCode is changed to invokeMurmurHash3.productHash
directly and mix in the name to the seed statically. This works out with keepingproductHash
forwards and backwards compatible.The
MurmurHash3.productHash
method is deprecated / renamed tocaseClassHash
. This method computes the same hash as the synthetichashCode
, except for the corner case where a case class (or a subclass) override theproductPrefix
. In this case, the case class name needs to be passed manually tocaseClassHash
.Fixes scala/bug#13033