aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2017-02-14 11:17:53 +0100
committerMartin Odersky <odersky@gmail.com>2017-04-04 13:29:38 +0200
commitcf10e28a54aaeab124f9a939f71da7e09d299bcb (patch)
treef48e018cc4a02d955366db9b7b31315c6502127e
parent4bdad3c21a1461bed6e91ef69dd767fa5211f60d (diff)
downloaddotty-cf10e28a54aaeab124f9a939f71da7e09d299bcb.tar.gz
dotty-cf10e28a54aaeab124f9a939f71da7e09d299bcb.tar.bz2
dotty-cf10e28a54aaeab124f9a939f71da7e09d299bcb.zip
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.
-rw-r--r--compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala26
-rw-r--r--compiler/src/dotty/tools/dotc/core/StdNames.scala1
-rw-r--r--library/src/scala/runtime/EnumValues.scala25
-rw-r--r--tests/run/generic/Color.scala3
-rw-r--r--tests/run/generic/SearchResult.scala3
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 {