Skip to content

Commit 0f2fdcb

Browse files
Synthetically generated oridnal method for enums
1 parent 8aeaa8a commit 0f2fdcb

File tree

5 files changed

+23
-9
lines changed

5 files changed

+23
-9
lines changed

compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,9 @@ object DesugarEnums {
142142
body = List(ordinalDef, toStringDef) ++ registerCall
143143
).withAttachment(ExtendsSingletonMirror, ()))
144144
DefDef(nme.DOLLAR_NEW, Nil,
145-
List(List(param(nme.nameDollar, defn.StringType), param(nme.ordinalDollar_, defn.IntType))),
145+
List(List(param(nme.ordinalDollar_, defn.IntType), param(nme.nameDollar, defn.StringType))),
146146
TypeTree(), creator).withFlags(Private | Synthetic)
147-
}.reporting(e => s"marker\n${e.show}")
147+
}
148148

149149
/** The return type of an enum case apply method and any widening methods in which
150150
* the apply's right hand side will be wrapped. For parents of the form
@@ -304,7 +304,7 @@ object DesugarEnums {
304304
}
305305
else {
306306
val (tag, scaffolding) = nextOrdinal(CaseKind.Simple)
307-
val creator = Apply(Ident(nme.DOLLAR_NEW), List(Literal(Constant(name.toString)), Literal(Constant(tag))))
307+
val creator = Apply(Ident(nme.DOLLAR_NEW), List(Literal(Constant(tag)), Literal(Constant(name.toString))))
308308
val vdef = ValDef(name, enumClassRef, creator).withMods(mods | Final)
309309
flatTree(scaffolding ::: vdef :: Nil).withSpan(span)
310310
}

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,8 @@ class Definitions {
678678
def NoneClass(implicit ctx: Context): ClassSymbol = NoneModuleRef.symbol.moduleClass.asClass
679679
lazy val EnumType: TypeRef = ctx.requiredClassRef("scala.Enum")
680680
def EnumClass(implicit ctx: Context): ClassSymbol = EnumType.symbol.asClass
681+
lazy val Enum_ordinalR: TermRef = EnumClass.requiredMethodRef(nme.ordinal)
682+
def Enum_ordinal(implicit ctx: Context): Symbol = Enum_ordinalR.symbol
681683
lazy val JEnumType: TypeRef = ctx.requiredClassRef("scala.compat.JEnum")
682684
def JEnumClass(implicit ctx: Context): ClassSymbol = JEnumType.symbol.asClass
683685
lazy val EnumValuesType: TypeRef = ctx.requiredClassRef("scala.runtime.EnumValues")

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ import DenotTransformers._
1616
object CompleteJavaEnums {
1717
val name: String = "completeJavaEnums"
1818

19-
private val nameParamName: TermName = "$name".toTermName
20-
private val ordinalParamName: TermName = "$ordinal".toTermName
19+
private val nameParamName: TermName = "_$name".toTermName
20+
private val ordinalParamName: TermName = "_$ordinal".toTermName
2121
}
2222

2323
/** For Scala enums that inherit from java.lang.Enum:
@@ -152,7 +152,7 @@ class CompleteJavaEnums extends MiniPhase with InfoTransformer { thisPhase =>
152152
templ.body.collect {
153153
case mdef: DefDef if mdef.name == name => mdef.rhs
154154
}.head
155-
val args = List(rhsOf(nme.toString_), rhsOf(nme.ordinal))
155+
val args = List(rhsOf(nme.toString_), rhsOf(nme.ordinalDollar))
156156
cpy.Template(templ)(
157157
parents = addEnumConstrArgs(cls.owner.owner.linkedClass, templ.parents, args))
158158
}

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,18 +56,21 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
5656
private[this] var myValueSymbols: List[Symbol] = Nil
5757
private[this] var myCaseSymbols: List[Symbol] = Nil
5858
private[this] var myCaseModuleSymbols: List[Symbol] = Nil
59+
private[this] var myEnumCaseSymbols: List[Symbol] = Nil
5960

6061
private def initSymbols(implicit ctx: Context) =
6162
if (myValueSymbols.isEmpty) {
6263
myValueSymbols = List(defn.Any_hashCode, defn.Any_equals)
6364
myCaseSymbols = myValueSymbols ++ List(defn.Any_toString, defn.Product_canEqual,
6465
defn.Product_productArity, defn.Product_productPrefix, defn.Product_productElement)
6566
myCaseModuleSymbols = myCaseSymbols.filter(_ ne defn.Any_equals)
67+
myEnumCaseSymbols = List(defn.Enum_ordinal)
6668
}
6769

6870
def valueSymbols(implicit ctx: Context): List[Symbol] = { initSymbols; myValueSymbols }
6971
def caseSymbols(implicit ctx: Context): List[Symbol] = { initSymbols; myCaseSymbols }
7072
def caseModuleSymbols(implicit ctx: Context): List[Symbol] = { initSymbols; myCaseModuleSymbols }
73+
def enumCaseSymbols(implicit ctx: Context): List[Symbol] = { initSymbols; myEnumCaseSymbols }
7174

7275
private def existingDef(sym: Symbol, clazz: ClassSymbol)(implicit ctx: Context): Symbol = {
7376
val existing = sym.matchingMember(clazz.thisType)
@@ -86,12 +89,15 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
8689
lazy val accessors =
8790
if (isDerivedValueClass(clazz)) clazz.paramAccessors.take(1) // Tail parameters can only be `erased`
8891
else clazz.caseAccessors
92+
val isEnumCase = clazz.derivesFrom(defn.EnumClass)
8993

9094
val symbolsToSynthesize: List[Symbol] =
9195
if (clazz.is(Case)) {
9296
if (clazz.is(Module)) caseModuleSymbols
97+
else if (isEnumCase) caseSymbols ++ enumCaseSymbols
9398
else caseSymbols
9499
}
100+
else if (isEnumCase) enumCaseSymbols
95101
else if (isDerivedValueClass(clazz)) valueSymbols
96102
else Nil
97103

@@ -120,6 +126,7 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
120126
case nme.productArity => Literal(Constant(accessors.length))
121127
case nme.productPrefix => ownName
122128
case nme.productElement => productElementBody(accessors.length, vrefss.head.head)
129+
case nme.ordinal => Select(This(clazz), nme.ordinalDollar)
123130
}
124131
ctx.log(s"adding $synthetic to $clazz at ${ctx.phase}")
125132
synthesizeDef(synthetic, syntheticRHS)
@@ -362,7 +369,7 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
362369

363370
/** For an enum T:
364371
*
365-
* def ordinal(x: MirroredMonoType) = x.ordinal
372+
* def ordinal(x: MirroredMonoType) = x.$ordinal
366373
*
367374
* For sealed trait with children of normalized types C_1, ..., C_n:
368375
*
@@ -377,7 +384,13 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
377384
* O is O.type.
378385
*/
379386
def ordinalBody(cls: Symbol, param: Tree)(implicit ctx: Context): Tree =
380-
if (cls.is(Enum)) Apply(param.select(nme.ordinal), Nil)
387+
if (cls.is(Enum)) {
388+
val ordinalMeth = param.select(nme.ordinal)
389+
val derivesFromJEnum =
390+
cls.is(Enum, butNot = Case) &&
391+
cls.info.parents.exists(p => p.typeSymbol == defn.JEnumClass)
392+
if (derivesFromJEnum) Apply(ordinalMeth, Nil) else ordinalMeth
393+
}
381394
else {
382395
val cases =
383396
for ((child, idx) <- cls.children.zipWithIndex) yield {

tests/run/enums-java-compat.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
class JEnum {
22
def name: String = "Foo"
3-
def ordinal: Int = 10
43
def action = "fofofo"
54
}
65

0 commit comments

Comments
 (0)