@@ -95,58 +95,78 @@ object DesugarEnums {
95
95
/** The following lists of definitions for an enum type E and known value cases e_0, ..., e_n:
96
96
*
97
97
* private val $values = [e_0, ..., e_n : E]
98
- * @annotation.threadUnsafe private lazy val $valuesReverse =
99
- * scala.runtime.ScalaRuntime.wrapRefArray($values).map((x_0: E) => (x_0.enumLabel, x_0)).toMap
100
98
* def values = $values.clone
101
99
* def valueOf($name: String) =
102
- * try $valuesReverse($name) catch
103
- * {
104
- * case ex$: NoSuchElementException =>
105
- * throw new IllegalArgumentException("enum case not found: " + $name)
106
- * }
100
+ * val h = if $name == null then 0 else $name.hashCode
101
+ * var intermediate = -1
102
+ * h match {
103
+ * case 326467 =>
104
+ * if "e_0" equals $name then
105
+ * intermediate = 0
106
+ * ...
107
+ * case 426978 =>
108
+ * if "e_n" equals $name then
109
+ * intermediate = n
110
+ * }
111
+ * intermediate match {
112
+ * case 0 => e_0
113
+ * ...
114
+ * case n => e_n
115
+ * case _ => throw new IllegalArgumentException("case not found: " + $name)
116
+ * }
107
117
*/
108
118
private def enumScaffolding (enumCases : List [(Int , TermName )])(using Context ): List [Tree ] = {
109
119
import dotty .tools .dotc .transform .SymUtils .rawTypeRef
120
+
121
+ def const (arg : String | Int | Null | Unit ) = Literal (Constant (arg))
122
+
110
123
val rawEnumClassRef = rawRef(enumClass.typeRef)
111
124
extension (tpe : NamedType ) def ofRawEnum = AppliedTypeTree (ref(tpe), rawEnumClassRef)
112
125
113
126
val privateValuesDef =
114
127
ValDef (nme.DOLLAR_VALUES , TypeTree (), JavaSeqLiteral (enumCases.map((_, name) => Ident (name)), rawEnumClassRef))
115
128
.withFlags(Private | Synthetic )
116
129
117
- val privateReverseValuesDef =
118
- val wrapped = Apply (Select (ref(defn.ScalaRuntimeModule .termRef), nme.wrapRefArray), Ident (nme.DOLLAR_VALUES ))
119
- val mapper =
120
- val paramName = nme.syntheticParamName(0 )
121
- val paramDef = param(paramName, rawEnumClassRef)
122
- Function (paramDef :: Nil , Tuple (Select (Ident (paramName), nme.enumLabel) :: Ident (paramName) :: Nil ))
123
- val mapBody = Select (Apply (Select (wrapped, nme.map), mapper), nme.toMap)
124
- val annot = New (ref(defn.ThreadUnsafeAnnot .typeRef), Nil ).withSpan(ctx.tree.span)
125
- ValDef (nme.DOLLAR_VALUES_REVERSE , TypeTree (), mapBody)
126
- .withFlags(Private | Synthetic | Lazy ).withAnnotations(annot :: Nil )
127
-
128
130
val valuesDef =
129
131
DefDef (nme.values, Nil , Nil , defn.ArrayType .ofRawEnum, valuesDot(nme.clone_))
130
132
.withFlags(Synthetic )
131
133
132
- val valuesOfExnMessage = Apply (
133
- Select (Literal (Constant (" enum case not found: " )), nme.PLUS ), Ident (nme.nameDollar))
134
-
135
- val valuesOfBody = Try (
136
- expr = Apply (Ident (nme.DOLLAR_VALUES_REVERSE ), Ident (nme.nameDollar) :: Nil ),
137
- cases = CaseDef (
138
- pat = Typed (Ident (nme.DEFAULT_EXCEPTION_NAME ), TypeTree (defn.NoSuchElementExceptionType )),
139
- guard = EmptyTree ,
140
- body = Throw (New (TypeTree (defn.IllegalArgumentExceptionType ), List (valuesOfExnMessage :: Nil )))
141
- ) :: Nil ,
142
- finalizer = EmptyTree
143
- )
134
+ val valuesOfBody : Tree =
135
+ val nameHash = nme.syntheticParamName(0 )
136
+ val ordinal = nme.syntheticParamName(1 )
137
+ val nameHashDef =
138
+ ValDef (nameHash, TypeTree (defn.IntType ), If (
139
+ cond = Apply (Select (Ident (nme.nameDollar), nme.eq), const(null )),
140
+ thenp = const(0 ),
141
+ elsep = Select (Ident (nme.nameDollar), nme.hashCode_))).withFlags(Local )
142
+ val ordinalDef = ValDef (ordinal, TypeTree (defn.IntType ), const(- 1 )).withFlags(Local | Mutable )
143
+ val hashCases = enumCases.map { (ord, name) =>
144
+ val condAssign = If (
145
+ cond = Apply (Select (const(name.toString), nme.equals_), Ident (nme.nameDollar)),
146
+ thenp = Assign (Ident (ordinal), const(ord)),
147
+ elsep = const(()))
148
+ CaseDef (const(name.toString.hashCode), EmptyTree , condAssign)
149
+ } ::: CaseDef (Ident (nme.WILDCARD ), EmptyTree , const(())) :: Nil
150
+ val finalDefault =
151
+ val msg = Apply (Select (const(" enum case not found: " ), nme.PLUS ), Ident (nme.nameDollar))
152
+ CaseDef (
153
+ pat = Ident (nme.WILDCARD ),
154
+ guard = EmptyTree ,
155
+ body = Throw (New (TypeTree (defn.IllegalArgumentExceptionType ), List (msg :: Nil ))))
156
+ val intermediateCases = enumCases.map((ordinal, name) =>
157
+ CaseDef (const(ordinal), EmptyTree , Ident (name))
158
+ ) ::: finalDefault :: Nil
159
+ Block (
160
+ nameHashDef ::
161
+ ordinalDef ::
162
+ Match (Ident (nameHash), hashCases) :: Nil ,
163
+ Match (Ident (ordinal), intermediateCases)
164
+ )
144
165
val valueOfDef = DefDef (nme.valueOf, Nil , List (param(nme.nameDollar, defn.StringType ) :: Nil ),
145
166
TypeTree (), valuesOfBody)
146
167
.withFlags(Synthetic )
147
168
148
169
privateValuesDef ::
149
- privateReverseValuesDef ::
150
170
valuesDef ::
151
171
valueOfDef :: Nil
152
172
}
0 commit comments