Skip to content

Commit d59313d

Browse files
committed
Change enumeration members.
Based on the discussion in #1970, enumeration objects now have three public members: - valueOf: Map[Int, E] - withName: Map[String, E] - values: Iterable[E] Also, the variance of case type parameters is now the same as in the corresponding type parameter of the enum class.
1 parent 73d21ee commit d59313d

File tree

5 files changed

+32
-26
lines changed

5 files changed

+32
-26
lines changed

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

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ object DesugarEnums {
3434
}
3535

3636
/** Type parameters reconstituted from the constructor
37-
* of the `enum' class corresponding to an enum case
37+
* of the `enum' class corresponding to an enum case.
38+
* The variance is the same as the corresponding type parameter of the enum class.
3839
*/
3940
def reconstitutedEnumTypeParams(pos: Position)(implicit ctx: Context) = {
4041
val tparams = enumClass.primaryConstructor.info match {
@@ -43,11 +44,11 @@ object DesugarEnums {
4344
case _ =>
4445
Nil
4546
}
46-
for (tparam <- tparams) yield {
47+
(tparams, enumClass.typeParams).zipped.map { (tparam, ecTparam) =>
4748
val tbounds = new DerivedFromParamTree
4849
tbounds.pushAttachment(OriginalSymbol, tparam)
4950
TypeDef(tparam.name, tbounds)
50-
.withFlags(Param | PrivateLocal).withPos(pos)
51+
.withFlags(Param | PrivateLocal | ecTparam.flags & VarianceFlags).withPos(pos)
5152
}
5253
}
5354

@@ -64,7 +65,8 @@ object DesugarEnums {
6465
/** The following lists of definitions for an enum type E:
6566
*
6667
* private val $values = new EnumValues[E]
67-
* def valueOf: Int => E = $values
68+
* def valueOf = $values.fromInt
69+
* def withName = $values.fromName
6870
* def values = $values.values
6971
*
7072
* private def $new(tag: Int, name: String) = new E {
@@ -74,32 +76,32 @@ object DesugarEnums {
7476
* }
7577
*/
7678
private def enumScaffolding(implicit ctx: Context): List[Tree] = {
77-
val valsRef = Ident(nme.DOLLAR_VALUES)
79+
def valuesDot(name: String) = Select(Ident(nme.DOLLAR_VALUES), name.toTermName)
80+
def enumDefDef(name: String, select: String) =
81+
DefDef(name.toTermName, Nil, Nil, TypeTree(), valuesDot(select))
7882
def param(name: TermName, typ: Type) =
7983
ValDef(name, TypeTree(typ), EmptyTree).withFlags(Param)
8084
val privateValuesDef =
8185
ValDef(nme.DOLLAR_VALUES, TypeTree(),
8286
New(TypeTree(defn.EnumValuesType.appliedTo(enumClass.typeRef :: Nil)), ListOfNil))
8387
.withFlags(Private)
84-
val valueOfDef =
85-
DefDef(nme.valueOf, Nil, Nil,
86-
TypeTree(defn.FunctionOf(defn.IntType :: Nil, enumClass.typeRef)), valsRef)
87-
val valuesDef =
88-
DefDef(nme.values, Nil, Nil, TypeTree(), Select(valsRef, nme.values))
88+
val valueOfDef = enumDefDef("valueOf", "fromInt")
89+
val withNameDef = enumDefDef("withName", "fromName")
90+
val valuesDef = enumDefDef("values", "values")
8991
val enumTagDef =
9092
DefDef(nme.enumTag, Nil, Nil, TypeTree(), Ident(nme.tag))
9193
val toStringDef =
9294
DefDef(nme.toString_, Nil, Nil, TypeTree(), Ident(nme.name))
9395
.withFlags(Override)
9496
val registerStat =
95-
Apply(Select(valsRef, nme.register), This(EmptyTypeIdent) :: Nil)
97+
Apply(valuesDot("register"), This(EmptyTypeIdent) :: Nil)
9698
def creator = New(Template(emptyConstructor, enumClassRef :: Nil, EmptyValDef,
9799
List(enumTagDef, toStringDef, registerStat)))
98100
val newDef =
99101
DefDef(nme.DOLLAR_NEW, Nil,
100102
List(List(param(nme.tag, defn.IntType), param(nme.name, defn.StringType))),
101103
TypeTree(), creator)
102-
List(privateValuesDef, valueOfDef, valuesDef, newDef)
104+
List(privateValuesDef, valueOfDef, withNameDef, valuesDef, newDef)
103105
}
104106

105107
def expandEnumModule(name: TermName, impl: Template, mods: Modifiers, pos: Position)(implicit ctx: Context): Tree = {

compiler/src/dotty/tools/dotc/core/StdNames.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,6 @@ object StdNames {
475475
val productPrefix: N = "productPrefix"
476476
val readResolve: N = "readResolve"
477477
val reflect : N = "reflect"
478-
val register: N = "register"
479478
val reify : N = "reify"
480479
val rootMirror : N = "rootMirror"
481480
val runOrElse: N = "runOrElse"
Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
package scala.runtime
22

3-
import scala.collection.immutable.Seq
4-
import scala.collection.mutable.ResizableArray
3+
import scala.collection.immutable.Map
4+
5+
class EnumValues[E <: Enum] {
6+
private var myMap: Map[Int, E] = Map()
7+
private var fromNameCache: Map[String, E] = null
58

6-
class EnumValues[E <: Enum] extends ResizableArray[E] {
7-
private var valuesCache: List[E] = Nil
89
def register(v: E) = {
9-
ensureSize(v.enumTag + 1)
10-
size0 = size0 max (v.enumTag + 1)
11-
array(v.enumTag) = v
12-
valuesCache = null
10+
require(!myMap.contains(v.enumTag))
11+
myMap = myMap.updated(v.enumTag, v)
12+
fromNameCache = null
1313
}
14-
def values: Seq[E] = {
15-
if (valuesCache == null) valuesCache = array.filter(_ != null).toList.asInstanceOf[scala.List[E]]
16-
valuesCache
14+
15+
def fromInt: Map[Int, E] = myMap
16+
def fromName: Map[String, E] = {
17+
if (fromNameCache == null) fromNameCache = myMap.values.map(v => v.toString -> v).toMap
18+
fromNameCache
1719
}
20+
def values: Iterable[E] = myMap.values
1821
}

tests/run/generic/Color.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ sealed trait Color extends Enum
1313
object Color {
1414

1515
private val $values = new runtime.EnumValues[Color]
16-
def valueOf: Int => Color = $values
16+
def valueOf = $values.fromInt
17+
def withName = $values.fromName
1718
def values = $values.values
1819

1920
private def $new(tag: Int, name: String) = new Color {

tests/run/generic/SearchResult.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ sealed trait SearchResult extends Enum
1414
object SearchResult extends {
1515

1616
private val $values = new runtime.EnumValues[SearchResult]
17-
def valueOf: Int => SearchResult = $values
17+
def valueOf = $values.fromInt
18+
def withName = $values.fromName
1819
def values = $values.values
1920

2021
private def $new(tag: Int, name: String) = new SearchResult {

0 commit comments

Comments
 (0)