Skip to content

Commit 2e9b4a1

Browse files
mbovelaherlihymtrigueira
committed
Make hashcode of enum items stable
Co-authored-by: anna herlihy <herlihyap@gmail.com> Co-authored-by: Miguel Trigueira <12471808+mtrigueira@users.noreply.github.com>
1 parent 85f6303 commit 2e9b4a1

File tree

3 files changed

+15
-8
lines changed

3 files changed

+15
-8
lines changed

compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
6868
myCaseSymbols = defn.caseClassSynthesized
6969
myCaseModuleSymbols = myCaseSymbols.filter(_ ne defn.Any_equals)
7070
myEnumValueSymbols = List(defn.Product_productPrefix)
71-
myNonJavaEnumValueSymbols = myEnumValueSymbols :+ defn.Any_toString :+ defn.Enum_ordinal
71+
myNonJavaEnumValueSymbols = myEnumValueSymbols :+ defn.Any_toString :+ defn.Enum_ordinal :+ defn.Any_hashCode
7272
}
7373

7474
def valueSymbols(using Context): List[Symbol] = { initSymbols; myValueSymbols }
@@ -116,6 +116,12 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
116116
def syntheticDefIfMissing(sym: Symbol): List[Tree] =
117117
if (existingDef(sym, clazz).exists) Nil else syntheticDef(sym) :: Nil
118118

119+
def identifierRef: Tree =
120+
if isSimpleEnumValue then // owner is `def $new(_$ordinal: Int, $name: String) = new MyEnum { ... }`
121+
ref(clazz.owner.paramSymss.head.find(_.name == nme.nameDollar).get)
122+
else // assume owner is `val Foo = new MyEnum { def ordinal = 0 }`
123+
Literal(Constant(clazz.owner.name.toString))
124+
119125
def syntheticDef(sym: Symbol): Tree = {
120126
val synthetic = sym.copy(
121127
owner = clazz,
@@ -135,12 +141,6 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
135141
else
136142
identifierRef
137143

138-
def identifierRef: Tree =
139-
if isSimpleEnumValue then // owner is `def $new(_$ordinal: Int, $name: String) = new MyEnum { ... }`
140-
ref(clazz.owner.paramSymss.head.find(_.name == nme.nameDollar).get)
141-
else // assume owner is `val Foo = new MyEnum { def ordinal = 0 }`
142-
Literal(Constant(clazz.owner.name.toString))
143-
144144
def ordinalRef: Tree =
145145
if isSimpleEnumValue then // owner is `def $new(_$ordinal: Int, $name: String) = new MyEnum { ... }`
146146
ref(clazz.owner.paramSymss.head.find(_.name == nme.ordinalDollar_).get)
@@ -357,7 +357,8 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
357357
* For case classes with primitive paramters, see [[caseHashCodeBody]].
358358
*/
359359
def chooseHashcode(using Context) =
360-
if (accessors.isEmpty) Literal(Constant(ownName.hashCode))
360+
if (isNonJavaEnumValue) identifierRef.select(nme.hashCode_).appliedToTermArgs(Nil)
361+
else if (accessors.isEmpty) Literal(Constant(ownName.hashCode))
361362
else if (accessors.exists(_.info.finalResultType.classSymbol.isPrimitiveValueClass))
362363
caseHashCodeBody
363364
else
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
65
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
enum E:
2+
case A
3+
4+
@main def Test =
5+
println(E.A.hashCode)

0 commit comments

Comments
 (0)