Skip to content

Commit 56c1f52

Browse files
committed
Pre-check modifiers in Parsers
Adapted from #5525: Check that only access modifiers are legal for enums (both definitions and cases). This is useful as a pre-check, to avoid confusing error messages later.
1 parent b8b4790 commit 56c1f52

File tree

3 files changed

+48
-4
lines changed

3 files changed

+48
-4
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ object DesugarEnums {
288288
val toStringDef = toStringMethLit(name.toString)
289289
val impl1 = cpy.Template(impl)(body = List(ordinalDef, toStringDef) ++ registerCall)
290290
.withAttachment(ExtendsSingletonMirror, ())
291-
val vdef = ValDef(name, TypeTree(), New(impl1)).withMods(mods | EnumValue)
291+
val vdef = ValDef(name, TypeTree(), New(impl1)).withMods(mods.withAddedFlags(EnumValue, span))
292292
flatTree(scaffolding ::: vdef :: Nil).withSpan(span)
293293
}
294294
}
@@ -304,7 +304,7 @@ object DesugarEnums {
304304
else {
305305
val (tag, scaffolding) = nextOrdinal(CaseKind.Simple)
306306
val creator = Apply(Ident(nme.DOLLAR_NEW), List(Literal(Constant(tag)), Literal(Constant(name.toString))))
307-
val vdef = ValDef(name, enumClassRef, creator).withMods(mods | EnumValue)
307+
val vdef = ValDef(name, enumClassRef, creator).withMods(mods.withAddedFlags(EnumValue, span))
308308
flatTree(scaffolding ::: vdef :: Nil).withSpan(span)
309309
}
310310
}

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3330,22 +3330,29 @@ object Parsers {
33303330
}
33313331
}
33323332

3333+
private def checkAccessOnly(mods: Modifiers, where: String): Modifiers =
3334+
val mods1 = mods & (AccessFlags | Enum)
3335+
if mods1 ne mods then
3336+
syntaxError(s"Only access modifiers are allowed on enum $where")
3337+
mods1
3338+
33333339
/** EnumDef ::= id ClassConstr InheritClauses [‘with’] EnumBody
33343340
*/
33353341
def enumDef(start: Offset, mods: Modifiers): TypeDef = atSpan(start, nameStart) {
3342+
val mods1 = checkAccessOnly(mods, "definitions")
33363343
val modulName = ident()
33373344
in.endMarkerScope(modulName) {
33383345
val clsName = modulName.toTypeName
33393346
val constr = classConstr()
33403347
val templ = template(constr, isEnum = true)
3341-
finalizeDef(TypeDef(clsName, templ), mods, start)
3348+
finalizeDef(TypeDef(clsName, templ), mods1, start)
33423349
}
33433350
}
33443351

33453352
/** EnumCase = `case' (id ClassConstr [`extends' ConstrApps] | ids)
33463353
*/
33473354
def enumCase(start: Offset, mods: Modifiers): DefTree = {
3348-
val mods1 = mods | EnumCase
3355+
val mods1 = checkAccessOnly(mods, "cases") | EnumCase
33493356
accept(CASE)
33503357

33513358
atSpan(start, nameStart) {

tests/neg/i5525.scala

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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+
erased enum Foo6 {} // error: only access modifiers allowed
7+
override enum Foo7 {} // error: only access modifiers allowed
8+
inline enum Foo8 {} // error: only access modifiers allowed
9+
opaque enum Foo9 {} // error: only access modifiers allowed
10+
11+
enum Foo10 {
12+
abstract case C1() // error: only access modifiers allowed
13+
final case C2() // error: only access modifiers allowed
14+
sealed case C3() // error: only access modifiers allowed
15+
implicit case C4() // error: only access modifiers allowed
16+
lazy case C5() // error: only access modifiers allowed
17+
erased case C6() // error: only access modifiers allowed
18+
override case C7() // error: only access modifiers allowed
19+
private case C8() // ok
20+
protected case C9() // ok
21+
}
22+
23+
enum Foo11 {
24+
abstract case C1 // error: only access modifiers allowed
25+
final case C2 // error: only access modifiers allowed
26+
sealed case C3 // error: only access modifiers allowed
27+
implicit case C4 // error: only access modifiers allowed
28+
lazy case C5 // error: only access modifiers allowed
29+
erased case C6 // error: only access modifiers allowed
30+
override case C7 // error: only access modifiers allowed
31+
private case C8 // ok
32+
protected case C9 // ok
33+
}
34+
35+
enum Foo12 { // error: enums must contain at least one case
36+
inline case C10() // error // error // error (inline treated as ident here)
37+
}

0 commit comments

Comments
 (0)