Skip to content

Commit 805ec33

Browse files
committed
make values and valueOf only available on enumerations
1 parent bdc8092 commit 805ec33

File tree

8 files changed

+4026
-39
lines changed

8 files changed

+4026
-39
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ object DesugarEnums {
152152
}
153153

154154
private def enumLookupMethods(constraints: EnumConstraints)(using Context): List[Tree] =
155-
def scaffolding: List[Tree] = if constraints.cached then enumScaffolding(constraints.enumCases.map(_._2)) else Nil
155+
def scaffolding: List[Tree] = if constraints.isEnumeration then enumScaffolding(constraints.enumCases.map(_._2)) else Nil
156156
def valueCtor: List[Tree] = if constraints.requiresCreator then enumValueCreator :: Nil else Nil
157157
def byOrdinal: List[Tree] =
158158
if isJavaEnum || !constraints.cached then Nil

tests/neg/enum-values.scala

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
enum Tag[T]:
2+
case Int extends Tag[Int]
3+
case String extends Tag[String]
4+
case OfClass[T]()(using val tag: reflect.ClassTag[T]) extends Tag[T]
5+
6+
enum ListLike[+T]:
7+
case Cons[T](head: T, tail: ListLike[T]) extends ListLike[T]
8+
case EmptyListLike
9+
10+
enum TypeCtorsK[F[_]]:
11+
case List extends TypeCtorsK[List]
12+
case Option extends TypeCtorsK[Option]
13+
case Const[T]() extends TypeCtorsK[[U] =>> T]
14+
15+
def Test: Unit =
16+
import Tag._, ListLike._, TypeCtorsK._
17+
import reflect.Selectable.reflectiveSelectable
18+
19+
val tags: Array[Tag[?]] = Tag.values // error: value values is not a member of object Tag
20+
val listlikes: Array[ListLike[?]] = ListLike.values // error: value values is not a member of object ListLike
21+
val typeCtorsK: Array[TypeCtorsK[?]] = TypeCtorsK.values // error: value values is not a member of object TypeCtorsK
22+
23+
Tag.valueOf("Int") // error: value valueOf is not a member of object Tag
24+
ListLike.valueOf("EmptyListLike") // error: value valueOf is not a member of object ListLike
25+
TypeCtorsK.valueOf("Option") // error: value valueOf is not a member of object TypeCtorsK

tests/run/enum-custom-toString.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,17 +59,14 @@ object Tag:
5959
assert(EZ.E(0).productPrefix == "E", s"EZ.E(0).productPrefix = ${EZ.E(0).productPrefix}")
6060
assert(EC.F.toString == "F", s"EC.F.toString = ${EC.F.toString}")
6161
assert(EC.F.productPrefix == "F", s"EC.F.productPrefix = ${EC.F.productPrefix}")
62-
assert(EC.valueOf("F") == EC.F, s"EC.valueOf(F) = ${EC.valueOf("F")}")
6362
assert(EC.G(0).toString == "G(0)", s"EC.G(0).toString = ${EC.G(0).toString}")
6463
assert(EC.G(0).productPrefix == "G", s"EC.G(0).productPrefix = ${EC.G(0).productPrefix}")
6564
assert(EO.H.toString == "overridden", s"EO.H.toString = ${EO.H.toString}")
6665
assert(EO.H.productPrefix == "noprefix", s"EO.H.productPrefix = ${EO.H.productPrefix}")
67-
assert(EO.valueOf("H") == EO.H, s"EO.valueOf(H) = ${EO.valueOf("H")}")
6866
assert(EO.I(0).toString == "overridden", s"EO.I(0).toString = ${EO.I(0).toString}")
6967
assert(EO.I(0).productPrefix == "noprefix", s"EO.I(0).productPrefix = ${EO.I(0).productPrefix}")
7068
assert(EQ.J.toString == "overridden", s"EQ.J.toString = ${EQ.J.toString}")
7169
assert(EQ.J.productPrefix == "noprefix", s"EQ.J.productPrefix = ${EQ.J.productPrefix}")
72-
assert(EQ.valueOf("J") == EQ.J, s"EQ.valueOf(J) = ${EQ.valueOf("J")}")
7370
assert(EQ.K(0).toString == "overridden", s"EQ.K(0).toString = ${EQ.K(0).toString}")
7471
assert(EQ.K(0).productPrefix == "noprefix", s"EQ.K(0).productPrefix = ${EQ.K(0).productPrefix}")
7572
assert(Tag.IntTag.productPrefix == "", s"Tag.IntTag.productPrefix = ${Tag.IntTag.productPrefix}")

tests/run/enum-values.scala

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,49 +10,30 @@ enum Expr[-T >: Null]:
1010
case EmptyTree extends Expr[Null]
1111
case AnyTree
1212

13-
enum ListLike[+T]:
14-
case Cons[T](head: T, tail: ListLike[T]) extends ListLike[T]
15-
case EmptyListLike
16-
17-
enum TypeCtorsK[F[_]]:
18-
case List extends TypeCtorsK[List]
19-
case Option extends TypeCtorsK[Option]
20-
case Const[T]() extends TypeCtorsK[[U] =>> T]
21-
2213
enum MixedParams[F[_], G[X,Y] <: collection.Map[X,Y], T]:
2314
case Foo extends MixedParams[List, collection.mutable.LinkedHashMap, Unit]
2415

2516
@main def Test: Unit =
26-
import Color._, Tag._, Expr._, ListLike._, TypeCtorsK._, MixedParams._
17+
import Color._, Expr._, MixedParams._
2718
import reflect.Selectable.reflectiveSelectable
2819

2920
extension [A](t: A) def show = runtime.ScalaRunTime.stringOf(t)
3021

31-
val colors: Array[Color] = Color.values
32-
val tags: Array[Tag[?]] = Tag.values
33-
val exprs: Array[Expr[? >: Null]] = Expr.values
34-
val listlikes: Array[ListLike[?]] = ListLike.values
35-
val typeCtorsK: Array[TypeCtorsK[?]] = TypeCtorsK.values
36-
22+
val colors: Array[Color] = Color.values
23+
val exprs: Array[Expr[? >: Null]] = Expr.values
3724
val mixedParams: Array[MixedParams[?, ? <: [X, Y] =>> collection.Map[X, Y], ?]] = MixedParams.values
3825

3926
def sameAs[T](arr: Array[T], compare: T*): Unit =
4027
assert(arr sameElements compare, s"${arr.show} does not correspond to ${compare.show}")
4128

4229
sameAs(colors, Red, Green, Blue)
43-
sameAs(tags, Int, String)
4430
sameAs(exprs, EmptyTree, AnyTree)
45-
sameAs(listlikes, EmptyListLike)
46-
sameAs(typeCtorsK, List, Option)
4731
sameAs(mixedParams, Foo)
4832

4933
def singleton[E <: AnyRef](value: E, name: String, companion: { def valueOf(s: String): E}) =
5034
val lookup = companion.valueOf(name)
5135
assert(value eq lookup, s"${value.show} is not identical to ${lookup.show}")
5236

5337
singleton(Green, "Green", Color)
54-
singleton(String, "String", Tag)
5538
singleton(AnyTree, "AnyTree", Expr)
56-
singleton(EmptyListLike, "EmptyListLike", ListLike)
57-
singleton(Option, "Option", TypeCtorsK)
5839
singleton(Foo, "Foo", MixedParams)

tests/run/enums-java-compat.scala

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
1-
class JEnum {
2-
def name: String = "Foo"
3-
def action = "fofofo"
1+
trait JEnum[E <: JEnum[E]] { self: reflect.Enum =>
2+
final def name: String = productPrefix
43
}
54

6-
enum A extends JEnum {
5+
trait JEnumCompanion[E <: JEnum[E]] {
6+
def valueOf(name: String): E
7+
def values: Array[E]
8+
}
9+
10+
enum A extends JEnum[A] {
711
case MONDAY, TUESDAY, SATURDAY
812
case Stuff
9-
case Someday(x: String)
13+
// case Someday(x: String) // uncommenting this line will prevent `object A` from compiling
1014
def report = "Reported"
1115
}
16+
object A extends JEnumCompanion[A]
1217

1318
trait Foo1
1419
trait Bar
@@ -37,4 +42,4 @@ object Test {
3742
println("Correctly failed to retrieve illegal name, message: " + e.getMessage)
3843
}
3944
}
40-
}
45+
}

tests/semanticdb/metac.expect

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,7 @@ Schema => SemanticDB v4
641641
Uri => Enums.scala
642642
Text => empty
643643
Language => Scala
644-
Symbols => 181 entries
644+
Symbols => 177 entries
645645
Occurrences => 203 entries
646646

647647
Symbols:
@@ -699,7 +699,6 @@ _empty_/Enums.Maybe#`<init>`(). => primary ctor <init>
699699
_empty_/Enums.Maybe. => final object Maybe
700700
_empty_/Enums.Maybe.$fromOrdinal(). => method $fromOrdinal
701701
_empty_/Enums.Maybe.$fromOrdinal().(_$ordinal) => param _$ordinal
702-
_empty_/Enums.Maybe.$values. => val method $values
703702
_empty_/Enums.Maybe.Just# => final case enum class Just
704703
_empty_/Enums.Maybe.Just#[A] => covariant typeparam A
705704
_empty_/Enums.Maybe.Just#_1(). => method _1
@@ -721,9 +720,6 @@ _empty_/Enums.Maybe.Just.unapply(). => method unapply
721720
_empty_/Enums.Maybe.Just.unapply().(x$1) => param x$1
722721
_empty_/Enums.Maybe.Just.unapply().[A] => typeparam A
723722
_empty_/Enums.Maybe.None. => case val static enum method None
724-
_empty_/Enums.Maybe.valueOf(). => method valueOf
725-
_empty_/Enums.Maybe.valueOf().($name) => param $name
726-
_empty_/Enums.Maybe.values(). => method values
727723
_empty_/Enums.Planet# => abstract sealed enum class Planet
728724
_empty_/Enums.Planet#G. => final val method G
729725
_empty_/Enums.Planet#`<init>`(). => primary ctor <init>

0 commit comments

Comments
 (0)