Skip to content

Commit 16545ec

Browse files
committed
remove dollarordinal from Enum, reduce bytecode
1 parent 4dbe0b7 commit 16545ec

File tree

7 files changed

+38
-32
lines changed

7 files changed

+38
-32
lines changed

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,8 @@ object DesugarEnums {
125125
/** A creation method for a value of enum type `E`, which is defined as follows:
126126
*
127127
* private def $new(_$ordinal: Int, $name: String) = new E with scala.runtime.EnumValue {
128-
* def $ordinal = $tag
128+
* private[this] def $ordinal = _$ordinal // if deriving from jl.Enum
129+
* def ordinal = _$ordinal // if not deriving from jl.Enum
129130
* override def toString = $name
130131
* $values.register(this)
131132
* }
@@ -265,7 +266,9 @@ object DesugarEnums {
265266
ValDef(name, TypeTree(typ), EmptyTree).withFlags(Param)
266267

267268
def ordinalMeth(body: Tree)(using Context): DefDef =
268-
DefDef(nme.ordinalDollar, Nil, Nil, TypeTree(defn.IntType), body)
269+
val isJEnum = ctx.owner.linkedClass.derivesFrom(defn.JavaEnumClass)
270+
val method = DefDef(if isJEnum then nme.ordinalDollar else nme.ordinal, Nil, Nil, TypeTree(defn.IntType), body)
271+
if isJEnum then method.withMods(Modifiers(Private)) else method
269272

270273
def toStringMeth(body: Tree)(using Context): DefDef =
271274
DefDef(nme.toString_, Nil, Nil, TypeTree(defn.StringType), body).withFlags(Override)

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

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ class CompleteJavaEnums extends MiniPhase with InfoTransformer { thisPhase =>
4040
sym == defn.JavaEnumClass.primaryConstructor ||
4141
sym.owner.derivesFromJavaEnum))
4242
addConstrParams(sym.info)
43+
else if isJavaEnumValueImpl(sym) then
44+
sym.asClass.delete(tp.decl(nme.toString_).symbol)
45+
sym.asClass.delete(tp.decl(nme.ordinalDollar).symbol)
46+
tp
4347
else tp
4448

4549
/** Add constructor parameters `$name: String` and `$ordinal: Int` to the end of
@@ -62,9 +66,10 @@ class CompleteJavaEnums extends MiniPhase with InfoTransformer { thisPhase =>
6266
/** The list of parameter definitions `$name: String, $ordinal: Int`, in given `owner`
6367
* with given flags (either `Param` or `ParamAccessor`)
6468
*/
65-
private def addedParams(owner: Symbol, flag: FlagSet)(using Context): List[ValDef] = {
66-
val nameParam = newSymbol(owner, nameParamName, flag | Synthetic, defn.StringType, coord = owner.span)
67-
val ordinalParam = newSymbol(owner, ordinalParamName, flag | Synthetic, defn.IntType, coord = owner.span)
69+
private def addedParams(owner: Symbol, isLocal: Boolean, flag: FlagSet)(using Context): List[ValDef] = {
70+
val flags = flag | Synthetic | (if isLocal then Private | Deferred else EmptyFlags)
71+
val nameParam = newSymbol(owner, nameParamName, flags, defn.StringType, coord = owner.span)
72+
val ordinalParam = newSymbol(owner, ordinalParamName, flags, defn.IntType, coord = owner.span)
6873
List(ValDef(nameParam), ValDef(ordinalParam))
6974
}
7075

@@ -85,7 +90,7 @@ class CompleteJavaEnums extends MiniPhase with InfoTransformer { thisPhase =>
8590
val sym = tree.symbol
8691
if (sym.isConstructor && sym.owner.derivesFromJavaEnum)
8792
val tree1 = cpy.DefDef(tree)(
88-
vparamss = tree.vparamss.init :+ (tree.vparamss.last ++ addedParams(sym, Param)))
93+
vparamss = tree.vparamss.init :+ (tree.vparamss.last ++ addedParams(sym, isLocal=false, Param)))
8994
sym.setParamssFromDefs(tree1.tparams, tree1.vparamss)
9095
tree1
9196
else tree
@@ -107,6 +112,11 @@ class CompleteJavaEnums extends MiniPhase with InfoTransformer { thisPhase =>
107112
}
108113
}
109114

115+
private def isJavaEnumValueImpl(cls: Symbol)(using Context): Boolean =
116+
cls.isAnonymousClass
117+
&& ((cls.owner.name eq nme.DOLLAR_NEW) || cls.owner.isAllOf(EnumCase))
118+
&& cls.owner.owner.linkedClass.derivesFromJavaEnum
119+
110120
/** 1. If this is an enum class, add $name and $ordinal parameters to its
111121
* parameter accessors and pass them on to the java.lang.Enum constructor.
112122
*
@@ -116,38 +126,39 @@ class CompleteJavaEnums extends MiniPhase with InfoTransformer { thisPhase =>
116126
*
117127
* class $anon extends E(...) {
118128
* ...
119-
* def ordinal = N
120-
* def toString = S
129+
* private def $ordinal = N
130+
* override def toString = S
121131
* ...
122132
* }
123133
*
124134
* After the transform it is expanded to
125135
*
126136
* class $anon extends E(..., N, S) {
127-
* "same as before"
137+
* ...
138+
* "removed $ordinal and toString"
139+
* ...
128140
* }
129141
*/
130142
override def transformTemplate(templ: Template)(using Context): Template = {
131143
val cls = templ.symbol.owner
132-
if (cls.derivesFromJavaEnum) {
144+
if cls.derivesFromJavaEnum then
133145
val (params, rest) = decomposeTemplateBody(templ.body)
134-
val addedDefs = addedParams(cls, ParamAccessor)
146+
val addedDefs = addedParams(cls, isLocal=true, ParamAccessor)
135147
val addedSyms = addedDefs.map(_.symbol.entered)
136148
val addedForwarders = addedEnumForwarders(cls)
137149
cpy.Template(templ)(
138150
parents = addEnumConstrArgs(defn.JavaEnumClass, templ.parents, addedSyms.map(ref)),
139151
body = params ++ addedDefs ++ addedForwarders ++ rest)
140-
}
141-
else if (cls.isAnonymousClass && ((cls.owner.name eq nme.DOLLAR_NEW) || cls.owner.isAllOf(EnumCase)) &&
142-
cls.owner.owner.linkedClass.derivesFromJavaEnum) {
152+
else if isJavaEnumValueImpl(cls) then
143153
def rhsOf(name: TermName) =
144-
templ.body.collect {
145-
case mdef: DefDef if mdef.name == name => mdef.rhs
146-
}.head
154+
templ.body.collect({ case mdef: DefDef if mdef.name == name => mdef.rhs }).head
155+
def removeDefs(body: List[Tree], names: TermName*) =
156+
body.filterNot { case ndef: DefDef => names.contains(ndef.name); case _ => false }
147157
val args = List(rhsOf(nme.toString_), rhsOf(nme.ordinalDollar))
148158
cpy.Template(templ)(
149-
parents = addEnumConstrArgs(cls.owner.owner.linkedClass, templ.parents, args))
150-
}
159+
parents = addEnumConstrArgs(cls.owner.owner.linkedClass, templ.parents, args),
160+
body = removeDefs(templ.body, nme.toString_, nme.ordinalDollar)
161+
)
151162
else templ
152163
}
153164
}

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

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
5757
private var myValueSymbols: List[Symbol] = Nil
5858
private var myCaseSymbols: List[Symbol] = Nil
5959
private var myCaseModuleSymbols: List[Symbol] = Nil
60-
private var myEnumCaseSymbols: List[Symbol] = Nil
6160

6261
private def initSymbols(using Context) =
6362
if (myValueSymbols.isEmpty) {
@@ -66,13 +65,11 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
6665
defn.Product_productArity, defn.Product_productPrefix, defn.Product_productElement,
6766
defn.Product_productElementName)
6867
myCaseModuleSymbols = myCaseSymbols.filter(_ ne defn.Any_equals)
69-
myEnumCaseSymbols = List(defn.Enum_ordinal)
7068
}
7169

7270
def valueSymbols(using Context): List[Symbol] = { initSymbols; myValueSymbols }
7371
def caseSymbols(using Context): List[Symbol] = { initSymbols; myCaseSymbols }
7472
def caseModuleSymbols(using Context): List[Symbol] = { initSymbols; myCaseModuleSymbols }
75-
def enumCaseSymbols(using Context): List[Symbol] = { initSymbols; myEnumCaseSymbols }
7673

7774
private def existingDef(sym: Symbol, clazz: ClassSymbol)(using Context): Symbol = {
7875
val existing = sym.matchingMember(clazz.thisType)
@@ -96,9 +93,7 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
9693
val symbolsToSynthesize: List[Symbol] =
9794
if (clazz.is(Case))
9895
if (clazz.is(Module)) caseModuleSymbols
99-
else if (isEnumCase) caseSymbols ++ enumCaseSymbols
10096
else caseSymbols
101-
else if (isEnumCase) enumCaseSymbols
10297
else if (isDerivedValueClass(clazz)) valueSymbols
10398
else Nil
10499

@@ -128,7 +123,6 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
128123
case nme.productPrefix => ownName
129124
case nme.productElement => productElementBody(accessors.length, vrefss.head.head)
130125
case nme.productElementName => productElementNameBody(accessors.length, vrefss.head.head)
131-
case nme.ordinal => Select(This(clazz), nme.ordinalDollar)
132126
}
133127
report.log(s"adding $synthetic to $clazz at ${ctx.phase}")
134128
synthesizeDef(synthetic, syntheticRHS)

docs/docs/reference/enums/desugarEnums.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ map into `case class`es or `val`s.
3636
```
3737
expands to a `sealed abstract` class that extends the `scala.Enum` trait and
3838
an associated companion object that contains the defined cases, expanded according
39-
to rules (2 - 8). The enum trait starts with a compiler-generated import that imports
40-
the names `<caseIds>` of all cases so that they can be used without prefix in the trait.
39+
to rules (2 - 8). The enum class starts with a compiler-generated import that imports
40+
the names `<caseIds>` of all cases so that they can be used without prefix in the class.
4141
```scala
4242
sealed abstract class E ... extends <parents> with scala.Enum {
4343
import E.{ <caseIds> }

library/src-bootstrapped/scala/Enum.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,3 @@ trait Enum extends Product, Serializable:
55

66
/** A number uniquely identifying a case of an enum */
77
def ordinal: Int
8-
protected def $ordinal: Int
9-

library/src-non-bootstrapped/scala/Enum.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package scala
22

33
/** A base trait of all enum classes */
4-
trait Enum:
4+
trait Enum extends Product, Serializable:
55

66
/** A number uniquely identifying a case of an enum */
77
def ordinal: Int

tests/pos/enum-List-control.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
abstract sealed class List[T] extends Enum
22
object List {
33
final class Cons[T](x: T, xs: List[T]) extends List[T] {
4-
def $ordinal = 0
4+
def ordinal = 0
55
def canEqual(that: Any): Boolean = that.isInstanceOf[Cons[_]]
66
def productArity: Int = 2
77
def productElement(n: Int): Any = n match
@@ -12,7 +12,7 @@ object List {
1212
def apply[T](x: T, xs: List[T]): List[T] = new Cons(x, xs)
1313
}
1414
final class Nil[T]() extends List[T], runtime.EnumValue {
15-
def $ordinal = 1
15+
def ordinal = 1
1616
}
1717
object Nil {
1818
def apply[T](): List[T] = new Nil()

0 commit comments

Comments
 (0)