@@ -104,22 +104,30 @@ object DesugarEnums {
104104
105105 /** The following lists of definitions for an enum type E and known value cases e_0, ..., e_n:
106106 *
107- * private val $values = Array[E](e_0,...,e_n)(ClassTag[E](classOf[E]))
107+ * private val $values = Array[E](this. e_0,...,this. e_n)(ClassTag[E](classOf[E])): @unchecked
108108 * def values = $values.clone
109109 * def valueOf($name: String) = $name match {
110- * case "e_0" => e_0
110+ * case "e_0" => this. e_0
111111 * ...
112- * case "e_n" => e_n
112+ * case "e_n" => this. e_n
113113 * case _ => throw new IllegalArgumentException("case not found: " + $name)
114114 * }
115115 */
116116 private def enumScaffolding (enumValues : List [RefTree ])(using Context ): List [Tree ] = {
117117 val rawEnumClassRef = rawRef(enumClass.typeRef)
118118 extension (tpe : NamedType ) def ofRawEnum = AppliedTypeTree (ref(tpe), rawEnumClassRef)
119119
120- val lazyFlagOpt = if enumCompanion.owner.isStatic then EmptyFlags else Lazy
121- val privateValuesDef = ValDef (nme.DOLLAR_VALUES , TypeTree (), ArrayLiteral (enumValues, rawEnumClassRef))
122- .withFlags(Private | Synthetic | lazyFlagOpt)
120+ val privateValuesDef =
121+ val uncheckedValues =
122+ // Here we use an unchecked annotation to silence warnings from the init checker. Without it, we get a warning
123+ // that simple enum cases are promoting this from warm to initialised. This is because we are populating the
124+ // array by selecting enum values from `this`, a value under construction.
125+ // Singleton enum values always construct a new anonymous class, which will not be checked by the init-checker,
126+ // so this warning will always persist even if the implementation of the anonymous class is safe.
127+ // TODO: remove @unchecked after https://github.com/lampepfl/dotty-feature-requests/issues/135 is resolved.
128+ Annotated (ArrayLiteral (enumValues, rawEnumClassRef), New (ref(defn.UncheckedAnnot .typeRef)))
129+ ValDef (nme.DOLLAR_VALUES , TypeTree (), uncheckedValues)
130+ .withFlags(Private | Synthetic )
123131
124132 val valuesDef =
125133 DefDef (nme.values, Nil , Nil , defn.ArrayType .ofRawEnum, valuesDot(nme.clone_))
@@ -170,7 +178,6 @@ object DesugarEnums {
170178 * def ordinal = _$ordinal // if `E` does not derive from `java.lang.Enum`
171179 * def enumLabel = $name // if `E` does not derive from `java.lang.Enum`
172180 * def enumLabel = this.name // if `E` derives from `java.lang.Enum`
173- * $values.register(this)
174181 * }
175182 */
176183 private def enumValueCreator (using Context ) = {
@@ -307,8 +314,8 @@ object DesugarEnums {
307314 case name : TermName => (ordinal, name) :: seenCases
308315 case _ => seenCases
309316 if definesLookups then
310- val companionRef = ref(enumCompanion.termRef )
311- val cachedValues = cases.reverse.map((i, name) => (i, Select (companionRef , name)))
317+ val thisRef = This ( EmptyTypeIdent )
318+ val cachedValues = cases.reverse.map((i, name) => (i, Select (thisRef , name)))
312319 (ordinal, enumLookupMethods(EnumConstraints (minKind, maxKind, cachedValues)))
313320 else
314321 ctx.tree.pushAttachment(EnumCaseCount , (ordinal + 1 , minKind, maxKind, cases))
0 commit comments