Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 658c8bd

Browse files
authored
Allow into on enums (#23795)
2 parents 9e88707 + 8005ac3 commit 658c8bd

File tree

7 files changed

+160
-19
lines changed

7 files changed

+160
-19
lines changed

‎compiler/src/dotty/tools/dotc/parsing/Parsers.scala‎

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4263,18 +4263,21 @@ object Parsers {
42634263
finalizeDef(ModuleDef(name, templ), mods, start)
42644264
}
42654265

4266-
private def checkAccessOnly(mods: Modifiers, where: String): Modifiers =
4267-
// We allow `infix to mark the `enum`s type as infix.
4268-
// Syntax rules disallow the soft infix modifier on `case`s.
4269-
val mods1 = mods & (AccessFlags | Enum | Infix)
4270-
if mods1 ne mods then
4271-
syntaxError(em"Only access modifiers are allowed on enum $where")
4272-
mods1
4266+
private def checkAccessOnly(mods: Modifiers, caseStr: String): Modifiers =
4267+
// We allow `infix` and `into` on `enum` definitions.
4268+
// Syntax rules disallow these soft infix modifiers on `case`s.
4269+
val flags = mods.flags
4270+
var flags1 = flags
4271+
for mod <- mods.mods do
4272+
if !mod.flags.isOneOf(AccessFlags | Enum | Infix | Into) then
4273+
syntaxError(em"This modifier is not allowed on an enum$caseStr", mod.span)
4274+
flags1 = flags1 &~ mod.flags
4275+
if flags1 != flags then mods.withFlags(flags1) else mods
42734276

42744277
/** EnumDef ::= id ClassConstr InheritClauses EnumBody
42754278
*/
42764279
def enumDef(start: Offset, mods: Modifiers): TypeDef = atSpan(start, nameStart) {
4277-
val mods1 = checkAccessOnly(mods, "definitions")
4280+
val mods1 = checkAccessOnly(mods, "")
42784281
val modulName = ident()
42794282
val clsName = modulName.toTypeName
42804283
val constr = classConstr(ParamOwner.Class)
@@ -4285,7 +4288,7 @@ object Parsers {
42854288
/** EnumCase = `case' (id ClassConstr [`extends' ConstrApps] | ids)
42864289
*/
42874290
def enumCase(start: Offset, mods: Modifiers): DefTree = {
4288-
val mods1 = checkAccessOnly(mods, "cases") | EnumCase
4291+
val mods1 = checkAccessOnly(mods, " case") | EnumCase
42894292
accept(CASE)
42904293

42914294
atSpan(start, nameStart) {

‎docs/_docs/reference/enums/enums.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ The fields referenced by `Mercury` are not visible, and the fields referenced by
117117
be referenced directly (using `import Planet.*`). You must use an indirect reference,
118118
such as demonstrated with `Earth`.
119119

120+
Enum cases accept only access modifiers.
121+
Enum classes accept only access modifiers and `into` or `infix`.
122+
120123
## Deprecation of Enum Cases
121124

122125
As a library author, you may want to signal that an enum case is no longer intended for use. However you could still want to gracefully handle the removal of a case from your public API, such as special casing deprecated cases.

‎tests/neg/i23400.scala‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ case class Baz(foo: MyInto[Foo])
1414

1515
given Conversion[Int, Foo] = Foo(_)
1616

17-
into enum Color: // error
17+
into enum Color: // ok
1818
case Red, Green
1919

2020
def test =

‎tests/neg/i5525.check‎

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
-- Error: tests/neg/i5525.scala:1:0 ------------------------------------------------------------------------------------
2+
1 |abstract enum Foo1 { case C } // error: only access modifiers allowed
3+
|^^^^^^^^
4+
|This modifier is not allowed on an enum
5+
-- Error: tests/neg/i5525.scala:2:0 ------------------------------------------------------------------------------------
6+
2 |final enum Foo2 { case C } // error: only access modifiers allowed
7+
|^^^^^
8+
|This modifier is not allowed on an enum
9+
-- Error: tests/neg/i5525.scala:3:0 ------------------------------------------------------------------------------------
10+
3 |sealed enum Foo3 { case C } // error: only access modifiers allowed
11+
|^^^^^^
12+
|This modifier is not allowed on an enum
13+
-- Error: tests/neg/i5525.scala:4:0 ------------------------------------------------------------------------------------
14+
4 |implicit enum Foo4 { case C } // error: only access modifiers allowed
15+
|^^^^^^^^
16+
|This modifier is not allowed on an enum
17+
-- Error: tests/neg/i5525.scala:5:0 ------------------------------------------------------------------------------------
18+
5 |lazy enum Foo5 { case C } // error: only access modifiers allowed
19+
|^^^^
20+
|This modifier is not allowed on an enum
21+
-- Error: tests/neg/i5525.scala:6:0 ------------------------------------------------------------------------------------
22+
6 |override enum Foo7 { case C } // error: only access modifiers allowed
23+
|^^^^^^^^
24+
|This modifier is not allowed on an enum
25+
-- Error: tests/neg/i5525.scala:7:0 ------------------------------------------------------------------------------------
26+
7 |inline enum Foo8 { case C } // error: only access modifiers allowed
27+
|^^^^^^
28+
|This modifier is not allowed on an enum
29+
-- Error: tests/neg/i5525.scala:8:0 ------------------------------------------------------------------------------------
30+
8 |opaque enum Foo9 { case C } // error: only access modifiers allowed
31+
|^^^^^^
32+
|This modifier is not allowed on an enum
33+
-- Error: tests/neg/i5525.scala:11:2 -----------------------------------------------------------------------------------
34+
11 | abstract case C1() // error: only access modifiers allowed
35+
| ^^^^^^^^
36+
| This modifier is not allowed on an enum case
37+
-- Error: tests/neg/i5525.scala:12:2 -----------------------------------------------------------------------------------
38+
12 | final case C2() // error: only access modifiers allowed
39+
| ^^^^^
40+
| This modifier is not allowed on an enum case
41+
-- Error: tests/neg/i5525.scala:13:2 -----------------------------------------------------------------------------------
42+
13 | sealed case C3() // error: only access modifiers allowed
43+
| ^^^^^^
44+
| This modifier is not allowed on an enum case
45+
-- Error: tests/neg/i5525.scala:14:2 -----------------------------------------------------------------------------------
46+
14 | implicit case C4() // error: only access modifiers allowed
47+
| ^^^^^^^^
48+
| This modifier is not allowed on an enum case
49+
-- Error: tests/neg/i5525.scala:15:2 -----------------------------------------------------------------------------------
50+
15 | lazy case C5() // error: only access modifiers allowed
51+
| ^^^^
52+
| This modifier is not allowed on an enum case
53+
-- Error: tests/neg/i5525.scala:16:2 -----------------------------------------------------------------------------------
54+
16 | override case C7() // error: only access modifiers allowed
55+
| ^^^^^^^^
56+
| This modifier is not allowed on an enum case
57+
-- Error: tests/neg/i5525.scala:22:2 -----------------------------------------------------------------------------------
58+
22 | abstract case C1 // error: only access modifiers allowed
59+
| ^^^^^^^^
60+
| This modifier is not allowed on an enum case
61+
-- Error: tests/neg/i5525.scala:23:2 -----------------------------------------------------------------------------------
62+
23 | final case C2 // error: only access modifiers allowed
63+
| ^^^^^
64+
| This modifier is not allowed on an enum case
65+
-- Error: tests/neg/i5525.scala:24:2 -----------------------------------------------------------------------------------
66+
24 | sealed case C3 // error: only access modifiers allowed
67+
| ^^^^^^
68+
| This modifier is not allowed on an enum case
69+
-- Error: tests/neg/i5525.scala:25:2 -----------------------------------------------------------------------------------
70+
25 | implicit case C4 // error: only access modifiers allowed
71+
| ^^^^^^^^
72+
| This modifier is not allowed on an enum case
73+
-- Error: tests/neg/i5525.scala:26:2 -----------------------------------------------------------------------------------
74+
26 | lazy case C5 // error: only access modifiers allowed
75+
| ^^^^
76+
| This modifier is not allowed on an enum case
77+
-- Error: tests/neg/i5525.scala:27:2 -----------------------------------------------------------------------------------
78+
27 | override case C7 // error: only access modifiers allowed
79+
| ^^^^^^^^
80+
| This modifier is not allowed on an enum case
81+
-- Error: tests/neg/i5525.scala:33:12 ----------------------------------------------------------------------------------
82+
33 | inline case C10() // error: only access modifiers allowed
83+
| ^^^^
84+
| end of statement expected but 'case' found
85+
-- Error: tests/neg/i5525.scala:36:0 -----------------------------------------------------------------------------------
86+
36 |final enum Foo13 { // error: only access modifiers and `into` allowed
87+
|^^^^^
88+
|This modifier is not allowed on an enum
89+
-- Error: tests/neg/i5525.scala:42:8 -----------------------------------------------------------------------------------
90+
42 | infix case C2 extends Foo14[Int, Int] // error // error
91+
| ^^^^
92+
| end of statement expected but 'case' found
93+
-- Error: tests/neg/i5525.scala:49:7 -----------------------------------------------------------------------------------
94+
49 | into case C1 // error
95+
| ^^^^
96+
| end of statement expected but 'case' found
97+
-- [E145] Syntax Error: tests/neg/i5525.scala:32:5 ---------------------------------------------------------------------
98+
32 |enum Foo12 { // error: Enumerations must contain at least one case
99+
| ^^^^^
100+
| Enumerations must contain at least one case
101+
|
102+
| longer explanation available when compiling with `-explain`
103+
-- [E006] Not Found Error: tests/neg/i5525.scala:42:2 ------------------------------------------------------------------
104+
42 | infix case C2 extends Foo14[Int, Int] // error // error
105+
| ^^^^^
106+
| Not found: infix
107+
|
108+
| longer explanation available when compiling with `-explain`
109+
-- [E129] Potential Issue Warning: tests/neg/i5525.scala:49:2 ----------------------------------------------------------
110+
49 | into case C1 // error
111+
| ^^^^
112+
| A pure expression does nothing in statement position
113+
|
114+
| longer explanation available when compiling with `-explain`

‎tests/neg/i5525.scala‎

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
abstract enum Foo1 {} // error: only access modifiers allowed
2-
final enum Foo2 {} // error: only access modifiers allowed
3-
sealed enum Foo3 {} // error: only access modifiers allowed
4-
implicit enum Foo4 {} // error: only access modifiers allowed
5-
lazy enum Foo5 {} // error: only access modifiers allowed
6-
override enum Foo7 {} // error: only access modifiers allowed
7-
inline enum Foo8 {} // error: only access modifiers allowed
8-
opaque enum Foo9 {} // error: only access modifiers allowed
1+
abstract enum Foo1 {caseC} // error: only access modifiers allowed
2+
final enum Foo2 {caseC} // error: only access modifiers allowed
3+
sealed enum Foo3 {caseC} // error: only access modifiers allowed
4+
implicit enum Foo4 {caseC} // error: only access modifiers allowed
5+
lazy enum Foo5 {caseC} // error: only access modifiers allowed
6+
override enum Foo7 {caseC} // error: only access modifiers allowed
7+
inline enum Foo8 {caseC} // error: only access modifiers allowed
8+
opaque enum Foo9 {caseC} // error: only access modifiers allowed
99

1010
enum Foo10 {
1111
abstract case C1() // error: only access modifiers allowed
@@ -31,4 +31,20 @@ enum Foo11 {
3131

3232
enum Foo12 { // error: Enumerations must contain at least one case
3333
inline case C10() // error: only access modifiers allowed
34+
}
35+
36+
final enum Foo13 { // error: only access modifiers and `into` allowed
37+
case C1
38+
}
39+
40+
infix enum Foo14[A, B]{ // OK
41+
case C1 extends Foo14[Int, Int]
42+
infix case C2 extends Foo14[Int, Int] // error // error
43+
}
44+
45+
import language.experimental.into
46+
47+
into enum Foo15 { // OK
48+
case C0
49+
into case C1 // error
3450
}

‎tests/neg/i5525b.scala‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//> using options -language:experimental.erasedDefinitions
22

3-
erased enum Foo6 {} // error: only access modifiers allowed
3+
erased enum Foo6 {caseC} // error: only access modifiers allowed
44

55
enum Foo10 { // error: Enumerations must contain at least one case
66
erased case C6() // error // error

‎tests/pos/infix-enum.scala‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
infix enum Foo[A, B]:
2+
case C1 extends Foo[Int, Int]
3+
4+
val x: Int Foo Int = Foo.C1
5+

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /