Skip to content

Commit 1818b99

Browse files
committed
Run CompleteJavaEnums after erasure
CompleteJavaEnums changes some signatures (it adds extra constructor parameters to classes extending java.lang.Enum), so it is not allowed to run before Erasure (this is enforced by the check added in TreeChecker in the previous commit). Moving CompleteJavaEnums after Erasure required one change, prior to this commit, constructor parameter were added to enum cases in two different places: - `def $new(...) = { new E { ... } }` was handled by transformDefDef - `val Foo = new E { ... }` was handled by transformTemplate It turns out that we can just let transformTemplate handle both cases, this simplifies the code and means that the Mixin phase can run after CompleteJavaEnums in the same group and see the transformed constructors.
1 parent 49af5b8 commit 1818b99

File tree

3 files changed

+9
-29
lines changed

3 files changed

+9
-29
lines changed

compiler/src/dotty/tools/dotc/Compiler.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ class Compiler {
6161
new CheckStatic, // Check restrictions that apply to @static members
6262
new BetaReduce, // Reduce closure applications
6363
new init.Checker) :: // Check initialization of objects
64-
List(new CompleteJavaEnums, // Fill in constructors for Java enums
65-
new ElimRepeated, // Rewrite vararg parameters and arguments
64+
List(new ElimRepeated, // Rewrite vararg parameters and arguments
6665
new ExpandSAMs, // Expand single abstract method closures to anonymous classes
6766
new ProtectedAccessors, // Add accessors for protected members
6867
new ExtensionMethods, // Expand methods of value classes with extension methods
@@ -101,6 +100,7 @@ class Compiler {
101100
new ArrayApply, // Optimize `scala.Array.apply([....])` and `scala.Array.apply(..., [....])` into `[...]`
102101
new ElimPolyFunction, // Rewrite PolyFunction subclasses to FunctionN subclasses
103102
new TailRec, // Rewrite tail recursion to loops
103+
new CompleteJavaEnums, // Fill in constructors for Java enums
104104
new Mixin, // Expand trait fields and trait initializers
105105
new LazyVals, // Expand lazy vals
106106
new Memoize, // Add private fields to getters and setters

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

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -77,38 +77,14 @@ class CompleteJavaEnums extends MiniPhase with InfoTransformer { thisPhase =>
7777
case p => p
7878
}
7979

80-
/** 1. If this is a constructor of a enum class that extends, add $name and $ordinal parameters to it.
81-
*
82-
* 2. If this is a $new method that creates simple cases, pass $name and $ordinal parameters
83-
* to the enum superclass. The $new method looks like this:
84-
*
85-
* def $new(..., ordinal: Int, name: String) = {
86-
* class $anon extends E(...) { ... }
87-
* new $anon
88-
* }
89-
*
90-
* After the transform it is expanded to
91-
*
92-
* def $new(..., ordinal: Int, name: String) = {
93-
* class $anon extends E(..., name, ordinal) { ... }
94-
* new $anon
95-
* }
96-
*/
80+
/** If this is a constructor of a enum class that extends, add $name and $ordinal parameters to it. */
9781
override def transformDefDef(tree: DefDef)(implicit ctx: Context): DefDef = {
9882
val sym = tree.symbol
9983
if (sym.isConstructor && sym.owner.derivesFromJavaEnum)
10084
val tree1 = cpy.DefDef(tree)(
10185
vparamss = tree.vparamss.init :+ (tree.vparamss.last ++ addedParams(sym, Param)))
10286
sym.setParamssFromDefs(tree1.tparams, tree1.vparamss)
10387
tree1
104-
else if (sym.name == nme.DOLLAR_NEW && sym.owner.linkedClass.derivesFromJavaEnum) {
105-
val Block((tdef @ TypeDef(tpnme.ANON_CLASS, templ: Template)) :: Nil, call) = tree.rhs
106-
val args = tree.vparamss.last.takeRight(2).map(param => ref(param.symbol)).reverse
107-
val templ1 = cpy.Template(templ)(
108-
parents = addEnumConstrArgs(sym.owner.linkedClass, templ.parents, args))
109-
cpy.DefDef(tree)(
110-
rhs = cpy.Block(tree.rhs)(cpy.TypeDef(tdef)(tdef.name, templ1) :: Nil, call))
111-
}
11288
else tree
11389
}
11490

@@ -159,7 +135,8 @@ class CompleteJavaEnums extends MiniPhase with InfoTransformer { thisPhase =>
159135
parents = addEnumConstrArgs(defn.JavaEnumClass, templ.parents, addedSyms.map(ref)),
160136
body = params ++ addedDefs ++ addedForwarders ++ rest)
161137
}
162-
else if (cls.isAnonymousClass && cls.owner.isAllOf(EnumCase) && cls.owner.owner.linkedClass.derivesFromJavaEnum) {
138+
else if (cls.isAnonymousClass && ((cls.owner.name eq nme.DOLLAR_NEW) || cls.owner.isAllOf(EnumCase)) &&
139+
cls.owner.owner.linkedClass.derivesFromJavaEnum) {
163140
def rhsOf(name: TermName) =
164141
templ.body.collect {
165142
case mdef: DefDef if mdef.name == name => mdef.rhs

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,10 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
112112
override def relaxedTypingInGroup: Boolean = true
113113
// Because it changes number of parameters in trait initializers
114114

115-
override def runsAfter: Set[String] = Set(Erasure.name)
115+
override def runsAfter: Set[String] = Set(
116+
Erasure.name,
117+
CompleteJavaEnums.name // This phase changes constructor parameters which Mixin translates into super-calls
118+
)
116119

117120
override def changesMembers: Boolean = true // the phase adds implementions of mixin accessors
118121

0 commit comments

Comments
 (0)