Skip to content

Commit 8832569

Browse files
committed
Move EnumValue to scala.runtime
It is no longer visible in the types of enum constants, so no need to keep it in Scala. Also, update doc pages to match the new scheme.
1 parent 6bd846a commit 8832569

File tree

10 files changed

+24
-16
lines changed

10 files changed

+24
-16
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ object DesugarEnums {
124124

125125
/** A creation method for a value of enum type `E`, which is defined as follows:
126126
*
127-
* private def $new(_$ordinal: Int, $name: String) = new E with EnumValue {
127+
* private def $new(_$ordinal: Int, $name: String) = new E with scala.runtime.EnumValue {
128128
* def $ordinal = $tag
129129
* override def toString = $name
130130
* $values.register(this)
@@ -135,7 +135,7 @@ object DesugarEnums {
135135
val toStringDef = toStringMeth(Ident(nme.nameDollar))
136136
val creator = New(Template(
137137
constr = emptyConstructor,
138-
parents = enumClassRef :: scalaDot(str.EnumValue.toTypeName) :: Nil,
138+
parents = enumClassRef :: scalaRuntimeDot(tpnme.EnumValue) :: Nil,
139139
derived = Nil,
140140
self = EmptyValDef,
141141
body = List(ordinalDef, toStringDef) ++ registerCall
@@ -287,7 +287,7 @@ object DesugarEnums {
287287
val ordinalDef = ordinalMethLit(tag)
288288
val toStringDef = toStringMethLit(name.toString)
289289
val impl1 = cpy.Template(impl)(
290-
parents = impl.parents :+ scalaDot(str.EnumValue.toTypeName),
290+
parents = impl.parents :+ scalaRuntimeDot(tpnme.EnumValue),
291291
body = List(ordinalDef, toStringDef) ++ registerCall)
292292
.withAttachment(ExtendsSingletonMirror, ())
293293
val vdef = ValDef(name, TypeTree(), New(impl1)).withMods(mods.withAddedFlags(EnumValue, span))

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
450450
def rootDot(name: Name)(implicit src: SourceFile): Select = Select(Ident(nme.ROOTPKG), name)
451451
def scalaDot(name: Name)(implicit src: SourceFile): Select = Select(rootDot(nme.scala), name)
452452
def scalaAnnotationDot(name: Name)(using SourceFile): Select = Select(scalaDot(nme.annotation), name)
453+
def scalaRuntimeDot(name: Name)(using SourceFile): Select = Select(scalaDot(nme.runtime), name)
453454
def scalaUnit(implicit src: SourceFile): Select = scalaDot(tpnme.Unit)
454455
def scalaAny(implicit src: SourceFile): Select = scalaDot(tpnme.Any)
455456
def javaDotLangDot(name: Name)(implicit src: SourceFile): Select = Select(Select(Ident(nme.java), nme.lang), name)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ trait ConstraintHandling[AbstractContext] {
300300
* (i.e. `inst.widenSingletons <:< bound` succeeds with satisfiable constraint)
301301
* 2. If `inst` is a union type, approximate the union type from above by an intersection
302302
* of all common base types, provided the result is a subtype of `bound`.
303-
* 3. If `inst` is an intersection with some protected base types, drop
303+
* 3. (currently not enabled) If `inst` is an intersection with some protected base types, drop
304304
* the protected base types from the intersection, provided the result is a subtype of `bound`.
305305
*
306306
* Don't do these widenings if `bound` is a subtype of `scala.Singleton`.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,7 @@ class Definitions {
639639
@tu lazy val EnumClass: ClassSymbol = ctx.requiredClass("scala.Enum")
640640
@tu lazy val Enum_ordinal: Symbol = EnumClass.requiredMethod(nme.ordinal)
641641

642-
@tu lazy val EnumValueClass: ClassSymbol = ctx.requiredClass("scala.EnumValue")
642+
@tu lazy val EnumValueClass: ClassSymbol = ctx.requiredClass("scala.runtime.EnumValue")
643643
@tu lazy val EnumValuesClass: ClassSymbol = ctx.requiredClass("scala.runtime.EnumValues")
644644
@tu lazy val ProductClass: ClassSymbol = ctx.requiredClass("scala.Product")
645645
@tu lazy val Product_canEqual : Symbol = ProductClass.requiredMethod(nme.canEqual_)

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ object StdNames {
3333

3434
final val MODULE_INSTANCE_FIELD = "MODULE$"
3535

36-
final val EnumValue = "EnumValue"
3736
final val Function = "Function"
3837
final val ErasedFunction = "ErasedFunction"
3938
final val ContextFunction = "ContextFunction"
@@ -358,15 +357,14 @@ object StdNames {
358357
val CAP: N = "CAP"
359358
val Constant: N = "Constant"
360359
val ConstantType: N = "ConstantType"
361-
val doubleHash: N = "doubleHash"
360+
val EnumValue: N = "EnumValue"
362361
val ExistentialTypeTree: N = "ExistentialTypeTree"
363362
val Flag : N = "Flag"
364363
val floatHash: N = "floatHash"
365364
val Ident: N = "Ident"
366365
val Import: N = "Import"
367366
val Literal: N = "Literal"
368367
val LiteralAnnotArg: N = "LiteralAnnotArg"
369-
val longHash: N = "longHash"
370368
val MatchCase: N = "MatchCase"
371369
val MirroredElemTypes: N = "MirroredElemTypes"
372370
val MirroredElemLabels: N = "MirroredElemLabels"
@@ -444,6 +442,7 @@ object StdNames {
444442
val delayedInitArg: N = "delayedInit$body"
445443
val derived: N = "derived"
446444
val derives: N = "derives"
445+
val doubleHash: N = "doubleHash"
447446
val drop: N = "drop"
448447
val dynamics: N = "dynamics"
449448
val elem: N = "elem"
@@ -506,6 +505,7 @@ object StdNames {
506505
val language: N = "language"
507506
val length: N = "length"
508507
val lengthCompare: N = "lengthCompare"
508+
val longHash: N = "longHash"
509509
val macroThis : N = "_this"
510510
val macroContext : N = "c"
511511
val main: N = "main"

docs/docs/reference/enums/desugarEnums.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,9 @@ map into `case class`es or `val`s.
126126
where `n` is the ordinal number of the case in the companion object,
127127
starting from 0. The statement `$values.register(this)` registers the value
128128
as one of the `values` of the enumeration (see below). `$values` is a
129-
compiler-defined private value in the companion object.
129+
compiler-defined private value in the companion object. The anonymous class also
130+
implements the abstract `Product` methods that it inherits from `Enum`.
131+
130132

131133
It is an error if a value case refers to a type parameter of the enclosing `enum`
132134
in a type argument of `<parents>`.
@@ -178,6 +180,7 @@ Companion objects of enumerations that contain at least one simple case define i
178180
}
179181
```
180182

183+
The anonymous class also implements the abstract `Product` methods that it inherits from `Enum`.
181184
The `$ordinal` method above is used to generate the `ordinal` method if the enum does not extend a `java.lang.Enum` (as Scala enums do not extend `java.lang.Enum`s unless explicitly specified). In case it does, there is no need to generate `ordinal` as `java.lang.Enum` defines it.
182185

183186
### Scopes for Enum Cases

docs/docs/reference/enums/enums.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ If you want to use the Scala-defined enums as Java enums, you can do so by exten
9595
enum Color extends java.lang.Enum[Color] { case Red, Green, Blue }
9696
```
9797

98-
The type parameter comes from the Java enum [definition](https://docs.oracle.com/javase/8/docs/api/index.html?java/lang/Enum.html) and should be the same as the type of the enum.
98+
The type parameter comes from the Java enum [definition](https://docs.oracle.com/javase/8/docs/api/index.html?java/lang/Enum.html) and should be the same as the type of the enum.
9999
There is no need to provide constructor arguments (as defined in the Java API docs) to `java.lang.Enum` when extending it – the compiler will generate them automatically.
100100

101101
After defining `Color` like that, you can use it like you would a Java enum:
@@ -116,7 +116,7 @@ This trait defines a single public method, `ordinal`:
116116
package scala
117117

118118
/** A base trait of all enum classes */
119-
trait Enum {
119+
trait Enum extends Product with Serializable {
120120

121121
/** A number uniquely identifying a case of an enum */
122122
def ordinal: Int

library/src/scala/EnumValue.scala renamed to library/src/scala/runtime/EnumValue.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package scala
1+
package scala.runtime
22

33
trait EnumValue extends Product, Serializable:
44
override def canEqual(that: Any) = this eq that.asInstanceOf[AnyRef]

tests/neg/enumvalues.scala

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
enum Color:
22
case Red, Green, Blue
33

4+
enum Option[+T]:
5+
case None extends Option[Nothing]
6+
7+
import scala.runtime.EnumValue
8+
49
@main def Test(c: Boolean) =
5-
// These currently give errors. But maybe we should make the actual
6-
// enum values carry the `EnumValue` trait, and only strip it from
7-
// user-defined vals and defs?
10+
// Verify that enum constants don't leak the scala.runtime.EnumValue trait
811
val x: EnumValue = if c then Color.Red else Color.Blue // error // error
912
val y: EnumValue = Color.Green // error
13+
val z: EnumValue = Option.None // error
1014

1115

tests/pos/enum-List-control.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ object List {
1111
object Cons {
1212
def apply[T](x: T, xs: List[T]): List[T] = new Cons(x, xs)
1313
}
14-
final class Nil[T]() extends List[T], EnumValue {
14+
final class Nil[T]() extends List[T], runtime.EnumValue {
1515
def $ordinal = 1
1616
}
1717
object Nil {

0 commit comments

Comments
 (0)