diff options
-rw-r--r-- | compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala | 26 | ||||
-rw-r--r-- | compiler/src/dotty/tools/dotc/core/StdNames.scala | 1 | ||||
-rw-r--r-- | library/src/scala/runtime/EnumValues.scala | 25 | ||||
-rw-r--r-- | tests/run/generic/Color.scala | 3 | ||||
-rw-r--r-- | tests/run/generic/SearchResult.scala | 3 |
5 files changed, 32 insertions, 26 deletions
diff --git a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala index 4317c8183..8bd3c8580 100644 --- a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala +++ b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala @@ -34,7 +34,8 @@ object DesugarEnums { } /** Type parameters reconstituted from the constructor - * of the `enum' class corresponding to an enum case + * of the `enum' class corresponding to an enum case. + * The variance is the same as the corresponding type parameter of the enum class. */ def reconstitutedEnumTypeParams(pos: Position)(implicit ctx: Context) = { val tparams = enumClass.primaryConstructor.info match { @@ -43,11 +44,11 @@ object DesugarEnums { case _ => Nil } - for (tparam <- tparams) yield { + (tparams, enumClass.typeParams).zipped.map { (tparam, ecTparam) => val tbounds = new DerivedFromParamTree tbounds.pushAttachment(OriginalSymbol, tparam) TypeDef(tparam.name, tbounds) - .withFlags(Param | PrivateLocal).withPos(pos) + .withFlags(Param | PrivateLocal | ecTparam.flags & VarianceFlags).withPos(pos) } } @@ -64,7 +65,8 @@ object DesugarEnums { /** The following lists of definitions for an enum type E: * * private val $values = new EnumValues[E] - * def valueOf: Int => E = $values + * def valueOf = $values.fromInt + * def withName = $values.fromName * def values = $values.values * * private def $new(tag: Int, name: String) = new E { @@ -74,32 +76,32 @@ object DesugarEnums { * } */ private def enumScaffolding(implicit ctx: Context): List[Tree] = { - val valsRef = Ident(nme.DOLLAR_VALUES) + def valuesDot(name: String) = Select(Ident(nme.DOLLAR_VALUES), name.toTermName) + def enumDefDef(name: String, select: String) = + DefDef(name.toTermName, Nil, Nil, TypeTree(), valuesDot(select)) def param(name: TermName, typ: Type) = ValDef(name, TypeTree(typ), EmptyTree).withFlags(Param) val privateValuesDef = ValDef(nme.DOLLAR_VALUES, TypeTree(), New(TypeTree(defn.EnumValuesType.appliedTo(enumClass.typeRef :: Nil)), ListOfNil)) .withFlags(Private) - val valueOfDef = - DefDef(nme.valueOf, Nil, Nil, - TypeTree(defn.FunctionOf(defn.IntType :: Nil, enumClass.typeRef)), valsRef) - val valuesDef = - DefDef(nme.values, Nil, Nil, TypeTree(), Select(valsRef, nme.values)) + val valueOfDef = enumDefDef("valueOf", "fromInt") + val withNameDef = enumDefDef("withName", "fromName") + val valuesDef = enumDefDef("values", "values") val enumTagDef = DefDef(nme.enumTag, Nil, Nil, TypeTree(), Ident(nme.tag)) val toStringDef = DefDef(nme.toString_, Nil, Nil, TypeTree(), Ident(nme.name)) .withFlags(Override) val registerStat = - Apply(Select(valsRef, nme.register), This(EmptyTypeIdent) :: Nil) + Apply(valuesDot("register"), This(EmptyTypeIdent) :: Nil) def creator = New(Template(emptyConstructor, enumClassRef :: Nil, EmptyValDef, List(enumTagDef, toStringDef, registerStat))) val newDef = DefDef(nme.DOLLAR_NEW, Nil, List(List(param(nme.tag, defn.IntType), param(nme.name, defn.StringType))), TypeTree(), creator) - List(privateValuesDef, valueOfDef, valuesDef, newDef) + List(privateValuesDef, valueOfDef, withNameDef, valuesDef, newDef) } def expandEnumModule(name: TermName, impl: Template, mods: Modifiers, pos: Position)(implicit ctx: Context): Tree = { diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index ff3ddbad7..bc3f96d91 100644 --- a/compiler/src/dotty/tools/dotc/core/StdNames.scala +++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala @@ -477,7 +477,6 @@ object StdNames { val productPrefix: N = "productPrefix" val readResolve: N = "readResolve" val reflect : N = "reflect" - val register: N = "register" val reify : N = "reify" val rootMirror : N = "rootMirror" val runOrElse: N = "runOrElse" diff --git a/library/src/scala/runtime/EnumValues.scala b/library/src/scala/runtime/EnumValues.scala index 6d2e56cf3..6f9d907b3 100644 --- a/library/src/scala/runtime/EnumValues.scala +++ b/library/src/scala/runtime/EnumValues.scala @@ -1,18 +1,21 @@ package scala.runtime -import scala.collection.immutable.Seq -import scala.collection.mutable.ResizableArray +import scala.collection.immutable.Map + +class EnumValues[E <: Enum] { + private var myMap: Map[Int, E] = Map() + private var fromNameCache: Map[String, E] = null -class EnumValues[E <: Enum] extends ResizableArray[E] { - private var valuesCache: List[E] = Nil def register(v: E) = { - ensureSize(v.enumTag + 1) - size0 = size0 max (v.enumTag + 1) - array(v.enumTag) = v - valuesCache = null + require(!myMap.contains(v.enumTag)) + myMap = myMap.updated(v.enumTag, v) + fromNameCache = null } - def values: Seq[E] = { - if (valuesCache == null) valuesCache = array.filter(_ != null).toList.asInstanceOf[scala.List[E]] - valuesCache + + def fromInt: Map[Int, E] = myMap + def fromName: Map[String, E] = { + if (fromNameCache == null) fromNameCache = myMap.values.map(v => v.toString -> v).toMap + fromNameCache } + def values: Iterable[E] = myMap.values } diff --git a/tests/run/generic/Color.scala b/tests/run/generic/Color.scala index 183f18349..7f2a8818c 100644 --- a/tests/run/generic/Color.scala +++ b/tests/run/generic/Color.scala @@ -13,7 +13,8 @@ sealed trait Color extends Enum object Color { private val $values = new runtime.EnumValues[Color] - def valueOf: Int => Color = $values + def valueOf = $values.fromInt + def withName = $values.fromName def values = $values.values private def $new(tag: Int, name: String) = new Color { diff --git a/tests/run/generic/SearchResult.scala b/tests/run/generic/SearchResult.scala index d39ee89a0..d4380a072 100644 --- a/tests/run/generic/SearchResult.scala +++ b/tests/run/generic/SearchResult.scala @@ -14,7 +14,8 @@ sealed trait SearchResult extends Enum object SearchResult extends { private val $values = new runtime.EnumValues[SearchResult] - def valueOf: Int => SearchResult = $values + def valueOf = $values.fromInt + def withName = $values.fromName def values = $values.values private def $new(tag: Int, name: String) = new SearchResult { |