@@ -95,58 +95,79 @@ object DesugarEnums {
9595 /** The following lists of definitions for an enum type E and known value cases e_0, ..., e_n:
9696 *
9797 * 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
10098 * def values = $values.clone
10199 * 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 nameHash = if $name == null then 0 else $name.hashCode
101+ * var ordinal = -1
102+ * nameHash match {
103+ * case 100054 =>
104+ * if "e_0" equals $name then
105+ * ordinal = 0
106+ * ...
107+ * case 100116 =>
108+ * if "e_n" equals $name then
109+ * ordinal = n
110+ * case _ =>
111+ * }
112+ * ordinal match {
113+ * case 0 => e_0
114+ * ...
115+ * case n => e_n
116+ * case _ => throw new IllegalArgumentException("case not found: " + $name)
117+ * }
107118 */
108119 private def enumScaffolding (enumCases : List [(Int , TermName )])(using Context ): List [Tree ] = {
109120 import dotty .tools .dotc .transform .SymUtils .rawTypeRef
121+
122+ def const (arg : String | Int | Null | Unit ) = Literal (Constant (arg))
123+
110124 val rawEnumClassRef = rawRef(enumClass.typeRef)
111125 extension (tpe : NamedType ) def ofRawEnum = AppliedTypeTree (ref(tpe), rawEnumClassRef)
112126
113127 val privateValuesDef =
114128 ValDef (nme.DOLLAR_VALUES , TypeTree (), JavaSeqLiteral (enumCases.map((_, name) => Ident (name)), rawEnumClassRef))
115129 .withFlags(Private | Synthetic )
116130
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-
128131 val valuesDef =
129132 DefDef (nme.values, Nil , Nil , defn.ArrayType .ofRawEnum, valuesDot(nme.clone_))
130133 .withFlags(Synthetic )
131134
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- )
135+ val valuesOfBody : Tree =
136+ val nameHash = nme.syntheticParamName(0 )
137+ val ordinal = nme.syntheticParamName(1 )
138+ val nameHashDef =
139+ ValDef (nameHash, TypeTree (defn.IntType ), If (
140+ cond = Apply (Select (Ident (nme.nameDollar), nme.eq), const(null )),
141+ thenp = const(0 ),
142+ elsep = Select (Ident (nme.nameDollar), nme.hashCode_))).withFlags(Local )
143+ val ordinalDef = ValDef (ordinal, TypeTree (defn.IntType ), const(- 1 )).withFlags(Local | Mutable )
144+ val hashCases = enumCases.map { (ord, name) =>
145+ val condAssign = If (
146+ cond = Apply (Select (const(name.toString), nme.equals_), Ident (nme.nameDollar)),
147+ thenp = Assign (Ident (ordinal), const(ord)),
148+ elsep = const(()))
149+ CaseDef (const(name.toString.hashCode), EmptyTree , condAssign)
150+ } ::: CaseDef (Ident (nme.WILDCARD ), EmptyTree , const(())) :: Nil
151+ val finalDefault =
152+ val msg = Apply (Select (const(" enum case not found: " ), nme.PLUS ), Ident (nme.nameDollar))
153+ CaseDef (
154+ pat = Ident (nme.WILDCARD ),
155+ guard = EmptyTree ,
156+ body = Throw (New (TypeTree (defn.IllegalArgumentExceptionType ), List (msg :: Nil ))))
157+ val intermediateCases = enumCases.map((ordinal, name) =>
158+ CaseDef (const(ordinal), EmptyTree , Ident (name))
159+ ) ::: finalDefault :: Nil
160+ Block (
161+ nameHashDef ::
162+ ordinalDef ::
163+ Match (Ident (nameHash), hashCases) :: Nil ,
164+ Match (Ident (ordinal), intermediateCases)
165+ )
144166 val valueOfDef = DefDef (nme.valueOf, Nil , List (param(nme.nameDollar, defn.StringType ) :: Nil ),
145167 TypeTree (), valuesOfBody)
146168 .withFlags(Synthetic )
147169
148170 privateValuesDef ::
149- privateReverseValuesDef ::
150171 valuesDef ::
151172 valueOfDef :: Nil
152173 }
0 commit comments