Skip to content

Commit c36af53

Browse files
committed
use qualified references to enum values
1 parent 8103650 commit c36af53

File tree

1 file changed

+19
-14
lines changed

1 file changed

+19
-14
lines changed

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

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,11 @@ object DesugarEnums {
2020
val Simple, Object, Class: Value = Value
2121
}
2222

23-
final class EnumConstraints(minKind: CaseKind.Value, maxKind: CaseKind.Value, cases: List[(Int, TermName)]):
24-
require(minKind <= maxKind && !(cached && cachedValues.isEmpty))
23+
final case class EnumConstraints(minKind: CaseKind.Value, maxKind: CaseKind.Value, enumCases: List[(Int, RefTree)]):
24+
require(minKind <= maxKind && !(cached && enumCases.isEmpty))
2525
def requiresCreator = minKind == CaseKind.Simple
2626
def isEnumeration = maxKind < CaseKind.Class
2727
def cached = minKind < CaseKind.Class
28-
def cachedValues = cases
2928
end EnumConstraints
3029

3130
/** Attachment containing the number of enum cases, the smallest kind that was seen so far,
@@ -47,6 +46,11 @@ object DesugarEnums {
4746
if (cls.is(Module)) cls.linkedClass else cls
4847
}
4948

49+
def enumCompanion(using Context): Symbol = {
50+
val cls = ctx.owner
51+
if (cls.is(Module)) cls.sourceModule else cls.linkedClass.sourceModule
52+
}
53+
5054
/** Is `tree` an (untyped) enum case? */
5155
def isEnumCase(tree: Tree)(using Context): Boolean = tree match {
5256
case tree: MemberDef => tree.mods.isEnumCase
@@ -109,14 +113,13 @@ object DesugarEnums {
109113
* case _ => throw new IllegalArgumentException("case not found: " + $name)
110114
* }
111115
*/
112-
private def enumScaffolding(enumCases: List[(Int, TermName)])(using Context): List[Tree] = {
116+
private def enumScaffolding(enumValues: List[RefTree])(using Context): List[Tree] = {
117+
val companionRef = ref(enumCompanion.termRef)
113118
val rawEnumClassRef = rawRef(enumClass.typeRef)
114119
extension (tpe: NamedType) def ofRawEnum = AppliedTypeTree(ref(tpe), rawEnumClassRef)
115120

116-
val privateValuesDef =
117-
ValDef(nme.DOLLAR_VALUES, TypeTree(),
118-
ArrayLiteral(enumCases.map((_, name) => Ident(name)), rawEnumClassRef))
119-
.withFlags(Private | Synthetic)
121+
val privateValuesDef = ValDef(nme.DOLLAR_VALUES, TypeTree(), ArrayLiteral(enumValues, rawEnumClassRef))
122+
.withFlags(Private | Synthetic)
120123

121124
val valuesDef =
122125
DefDef(nme.values, Nil, Nil, defn.ArrayType.ofRawEnum, valuesDot(nme.clone_))
@@ -127,8 +130,8 @@ object DesugarEnums {
127130
val msg = Apply(Select(Literal(Constant("enum case not found: ")), nme.PLUS), Ident(nme.nameDollar))
128131
CaseDef(Ident(nme.WILDCARD), EmptyTree,
129132
Throw(New(TypeTree(defn.IllegalArgumentExceptionType), List(msg :: Nil))))
130-
val stringCases = enumCases.map((_, name) =>
131-
CaseDef(Literal(Constant(name.toString)), EmptyTree, Ident(name))
133+
val stringCases = enumValues.map(enumValue =>
134+
CaseDef(Literal(Constant(enumValue.name.toString)), EmptyTree, enumValue)
132135
) ::: defaultCase :: Nil
133136
Match(Ident(nme.nameDollar), stringCases)
134137
val valueOfDef = DefDef(nme.valueOf, Nil, List(param(nme.nameDollar, defn.StringType) :: Nil),
@@ -141,7 +144,7 @@ object DesugarEnums {
141144
}
142145

143146
private def enumLookupMethods(constraints: EnumConstraints)(using Context): List[Tree] =
144-
def scaffolding: List[Tree] = if constraints.cached then enumScaffolding(constraints.cachedValues) else Nil
147+
def scaffolding: List[Tree] = if constraints.cached then enumScaffolding(constraints.enumCases.map(_._2)) else Nil
145148
def valueCtor: List[Tree] = if constraints.requiresCreator then enumValueCreator :: Nil else Nil
146149
def byOrdinal: List[Tree] =
147150
if isJavaEnum || !constraints.cached then Nil
@@ -150,8 +153,8 @@ object DesugarEnums {
150153
val ord = Ident(nme.ordinal)
151154
val err = Throw(New(TypeTree(defn.IndexOutOfBoundsException.typeRef), List(Select(ord, nme.toString_) :: Nil)))
152155
CaseDef(ord, EmptyTree, err)
153-
val valueCases = constraints.cachedValues.map((i, name) =>
154-
CaseDef(Literal(Constant(i)), EmptyTree, Ident(name))
156+
val valueCases = constraints.enumCases.map((i, enumValue) =>
157+
CaseDef(Literal(Constant(i)), EmptyTree, enumValue)
155158
) ::: defaultCase :: Nil
156159
val fromOrdinalDef = DefDef(nme.fromOrdinalDollar, Nil, List(param(nme.ordinalDollar_, defn.IntType) :: Nil),
157160
rawRef(enumClass.typeRef), Match(Ident(nme.ordinalDollar_), valueCases))
@@ -304,7 +307,9 @@ object DesugarEnums {
304307
case name: TermName => (ordinal, name) :: seenCases
305308
case _ => seenCases
306309
if definesLookups then
307-
(ordinal, enumLookupMethods(EnumConstraints(minKind, maxKind, cases.reverse)))
310+
val companionRef = ref(enumCompanion.termRef)
311+
val cachedValues = cases.reverse.map((i, name) => (i, Select(companionRef, name)))
312+
(ordinal, enumLookupMethods(EnumConstraints(minKind, maxKind, cachedValues)))
308313
else
309314
ctx.tree.pushAttachment(EnumCaseCount, (ordinal + 1, minKind, maxKind, cases))
310315
(ordinal, Nil)

0 commit comments

Comments
 (0)