Skip to content

Commit c064338

Browse files
committed
prevent leaks with simple cases
1 parent e34d09e commit c064338

File tree

2 files changed

+17
-6
lines changed

2 files changed

+17
-6
lines changed

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

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import dotty.tools.dotc.ast.Trees._
1616
import SymUtils._
1717

1818
import annotation.threadUnsafe
19-
import collection.mutable
2019

2120
object CompleteJavaEnums {
2221
val name: String = "completeJavaEnums"
@@ -116,13 +115,13 @@ class CompleteJavaEnums extends MiniPhase with InfoTransformer { thisPhase =>
116115
&& (((cls.owner.name eq nme.DOLLAR_NEW) && cls.owner.isAllOf(Private|Synthetic)) || cls.owner.isAllOf(EnumCase))
117116
&& cls.owner.owner.linkedClass.derivesFromJavaEnum
118117

119-
@threadUnsafe
120-
private lazy val enumCaseOrdinals: mutable.Map[Symbol, Int] = mutable.AnyRefMap.empty
118+
private val enumCaseOrdinals: MutableSymbolMap[Int] = newMutableSymbolMap
121119

122120
private def registerEnumClass(cls: Symbol)(using Context): Unit =
123121
cls.children.zipWithIndex.foreach(enumCaseOrdinals.put)
124122

125-
private def ordinalFor(enumCase: Symbol): Int = enumCaseOrdinals.remove(enumCase).get
123+
private def ordinalFor(enumCase: Symbol): Int =
124+
enumCaseOrdinals.remove(enumCase).get
126125

127126
/** 1. If this is an enum class, add $name and $ordinal parameters to its
128127
* parameter accessors and pass them on to the java.lang.Enum constructor.
@@ -145,17 +144,20 @@ class CompleteJavaEnums extends MiniPhase with InfoTransformer { thisPhase =>
145144
* "same as before"
146145
* }
147146
*/
148-
override def transformTemplate(templ: Template)(using Context): Template = {
147+
override def transformTemplate(templ: Template)(using Context): Tree = {
149148
val cls = templ.symbol.owner
150149
if cls.derivesFromJavaEnum then
151-
registerEnumClass(cls)
150+
registerEnumClass(cls) // invariant: class is visited before cases: see tests/pos/enum-companion-first.scala
152151
val (params, rest) = decomposeTemplateBody(templ.body)
153152
val addedDefs = addedParams(cls, isLocal=true, ParamAccessor)
154153
val addedSyms = addedDefs.map(_.symbol.entered)
155154
val addedForwarders = addedEnumForwarders(cls)
156155
cpy.Template(templ)(
157156
parents = addEnumConstrArgs(defn.JavaEnumClass, templ.parents, addedSyms.map(ref)),
158157
body = params ++ addedDefs ++ addedForwarders ++ rest)
158+
else if cls.linkedClass.derivesFromJavaEnum then
159+
enumCaseOrdinals.clear() // remove simple cases // invariant: companion is visited after cases
160+
templ
159161
else if isJavaEnumValueImpl(cls) then
160162
def creatorParamRef(name: TermName) =
161163
ref(cls.owner.paramSymss.head.find(_.name == name).get)

tests/pos/enum-companion-first.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
object Planet:
2+
final val G = 6.67300E-11
3+
4+
enum Planet(mass: Double, radius: Double) extends java.lang.Enum[Planet]:
5+
def surfaceGravity = Planet.G * mass / (radius * radius)
6+
def surfaceWeight(otherMass: Double) = otherMass * surfaceGravity
7+
8+
case Mercury extends Planet(3.303e+23, 2.4397e6)
9+
case Venus extends Planet(4.869e+24, 6.0518e6)

0 commit comments

Comments
 (0)