Skip to content

Commit 9ffbd1c

Browse files
committed
stub valueOf and values for non-enumeration
1 parent 8125006 commit 9ffbd1c

File tree

4 files changed

+61
-8
lines changed

4 files changed

+61
-8
lines changed

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

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,31 @@ object DesugarEnums {
151151
valueOfDef :: Nil
152152
}
153153

154+
/** This generates the same public API as `enumScaffolding`, but stubs implementations to fail at compiletime and
155+
* not generate bytecode
156+
*/
157+
private def enumScaffoldingStubbed(using Context): List[Tree] = {
158+
val rawEnumClassRef = rawRef(enumClass.typeRef)
159+
extension (tpe: NamedType) def ofRawEnum = AppliedTypeTree(ref(tpe), rawEnumClassRef)
160+
161+
def stub(description: String) = Apply(ref(defn.Compiletime_error), Literal(Constant(
162+
i"Although $enumClass is an enum, it has non-singleton cases, which prevents it from having a $description")))
163+
164+
val valuesDef = DefDef(nme.values, Nil, Nil, defn.ArrayType.ofRawEnum, stub(i"${nme.values} array"))
165+
.withFlags(Synthetic | Inline)
166+
167+
val valueOfDef = DefDef(nme.valueOf, Nil, List(param(nme.nameDollar, defn.StringType) :: Nil),
168+
TypeTree(), stub(i"${nme.valueOf} lookup method"))
169+
.withFlags(Synthetic | Inline)
170+
171+
valuesDef ::
172+
valueOfDef :: Nil
173+
}
174+
154175
private def enumLookupMethods(constraints: EnumConstraints)(using Context): List[Tree] =
155-
def scaffolding: List[Tree] = if constraints.isEnumeration then enumScaffolding(constraints.enumCases.map(_._2)) else Nil
176+
def scaffolding: List[Tree] =
177+
if constraints.isEnumeration then enumScaffolding(constraints.enumCases.map(_._2))
178+
else enumScaffoldingStubbed
156179
def valueCtor: List[Tree] = if constraints.requiresCreator then enumValueCreator :: Nil else Nil
157180
def byOrdinal: List[Tree] =
158181
if isJavaEnum || !constraints.cached then Nil

tests/neg/enum-values.check

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
-- Error: tests/neg/enum-values.scala:19:45 ----------------------------------------------------------------------------
2+
19 | val tags: Array[Tag[?]] = Tag.values // error
3+
| ^^^^^^^^^^
4+
| Although class Tag is an enum, it has non-singleton cases, which prevents it from having a values array
5+
-- Error: tests/neg/enum-values.scala:20:50 ----------------------------------------------------------------------------
6+
20 | val listlikes: Array[ListLike[?]] = ListLike.values // error
7+
| ^^^^^^^^^^^^^^^
8+
| Although class ListLike is an enum, it has non-singleton cases, which prevents it from having a values array
9+
-- Error: tests/neg/enum-values.scala:21:52 ----------------------------------------------------------------------------
10+
21 | val typeCtorsK: Array[TypeCtorsK[?]] = TypeCtorsK.values // error
11+
| ^^^^^^^^^^^^^^^^^
12+
| Although class TypeCtorsK is an enum, it has non-singleton cases, which prevents it from having a values array
13+
-- Error: tests/neg/enum-values.scala:23:13 ----------------------------------------------------------------------------
14+
23 | Tag.valueOf("Int") // error
15+
| ^^^^^^^^^^^^^^^^^^
16+
|Although class Tag is an enum, it has non-singleton cases, which prevents it from having a valueOf lookup method
17+
-- Error: tests/neg/enum-values.scala:24:18 ----------------------------------------------------------------------------
18+
24 | ListLike.valueOf("EmptyListLike") // error
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20+
|Although class ListLike is an enum, it has non-singleton cases, which prevents it from having a valueOf lookup method
21+
-- Error: tests/neg/enum-values.scala:25:20 ----------------------------------------------------------------------------
22+
25 | TypeCtorsK.valueOf("Option") // error
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24+
|Although class TypeCtorsK is an enum, it has non-singleton cases, which prevents it from having a valueOf lookup method

tests/neg/enum-values.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ def Test: Unit =
1616
import Tag._, ListLike._, TypeCtorsK._
1717
import reflect.Selectable.reflectiveSelectable
1818

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
19+
val tags: Array[Tag[?]] = Tag.values // error
20+
val listlikes: Array[ListLike[?]] = ListLike.values // error
21+
val typeCtorsK: Array[TypeCtorsK[?]] = TypeCtorsK.values // error
2222

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
23+
Tag.valueOf("Int") // error
24+
ListLike.valueOf("EmptyListLike") // error
25+
TypeCtorsK.valueOf("Option") // error

tests/semanticdb/metac.expect

Lines changed: 7 additions & 1 deletion
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 => 177 entries
644+
Symbols => 183 entries
645645
Occurrences => 203 entries
646646

647647
Symbols:
@@ -720,6 +720,9 @@ _empty_/Enums.Maybe.Just.unapply(). => method unapply
720720
_empty_/Enums.Maybe.Just.unapply().(x$1) => param x$1
721721
_empty_/Enums.Maybe.Just.unapply().[A] => typeparam A
722722
_empty_/Enums.Maybe.None. => case val static enum method None
723+
_empty_/Enums.Maybe.valueOf(). => macro valueOf
724+
_empty_/Enums.Maybe.valueOf().($name) => param $name
725+
_empty_/Enums.Maybe.values(). => macro values
723726
_empty_/Enums.Planet# => abstract sealed enum class Planet
724727
_empty_/Enums.Planet#G. => final val method G
725728
_empty_/Enums.Planet#`<init>`(). => primary ctor <init>
@@ -815,6 +818,9 @@ _empty_/Enums.`<:<`.Refl.unapply().(x$1) => param x$1
815818
_empty_/Enums.`<:<`.Refl.unapply().[C] => typeparam C
816819
_empty_/Enums.`<:<`.given_T(). => final implicit method given_T
817820
_empty_/Enums.`<:<`.given_T().[T] => typeparam T
821+
_empty_/Enums.`<:<`.valueOf(). => macro valueOf
822+
_empty_/Enums.`<:<`.valueOf().($name) => param $name
823+
_empty_/Enums.`<:<`.values(). => macro values
818824
_empty_/Enums.extension_unwrap(). => method extension_unwrap
819825
_empty_/Enums.extension_unwrap().(ev) => implicit param ev
820826
_empty_/Enums.extension_unwrap().(opt) => param opt

0 commit comments

Comments
 (0)