Skip to content

Commit 851f371

Browse files
authored
Merge pull request #6067 from dotty-staging/followup-6002
Follow up to #6002
2 parents 296222f + 9d6a9a2 commit 851f371

File tree

3 files changed

+26
-20
lines changed

3 files changed

+26
-20
lines changed

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,8 @@ object desugar {
341341
case _ => false
342342
}
343343

344+
def namePos = cdef.sourcePos.withSpan(cdef.nameSpan)
345+
344346
val isObject = mods.is(Module)
345347
val isCaseClass = mods.is(Case) && !isObject
346348
val isCaseObject = mods.is(Case) && isObject
@@ -361,10 +363,10 @@ object desugar {
361363
val constrVparamss =
362364
if (originalVparamss.isEmpty) { // ensure parameter list is non-empty
363365
if (isCaseClass && originalTparams.isEmpty)
364-
ctx.error(CaseClassMissingParamList(cdef), cdef.sourcePos.withSpan(cdef.nameSpan))
366+
ctx.error(CaseClassMissingParamList(cdef), namePos)
365367
ListOfNil
366368
} else if (isCaseClass && originalVparamss.head.exists(_.mods.is(Implicit))) {
367-
ctx.error("Case classes should have a non-implicit parameter list", cdef.sourcePos.withSpan(cdef.nameSpan))
369+
ctx.error("Case classes should have a non-implicit parameter list", namePos)
368370
ListOfNil
369371
}
370372
else originalVparamss.nestedMap(toDefParam)
@@ -391,6 +393,8 @@ object desugar {
391393
val stats = impl.body.map(expandConstructor)
392394
if (isEnum) {
393395
val (enumCases, enumStats) = stats.partition(DesugarEnums.isEnumCase)
396+
if (enumCases.isEmpty)
397+
ctx.error("Enumerations must constain at least one case", namePos)
394398
val enumCompanionRef = new TermRefTree()
395399
val enumImport = Import(impliedOnly = false, enumCompanionRef, enumCases.flatMap(caseIds))
396400
(enumImport :: enumStats, enumCases, enumCompanionRef)

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

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -368,9 +368,9 @@ object Parsers {
368368
}
369369

370370
private[this] var inEnum = false
371-
private def withinEnum[T](isEnum: Boolean)(body: => T): T = {
371+
private def withinEnum[T](body: => T): T = {
372372
val saved = inEnum
373-
inEnum = isEnum
373+
inEnum = true
374374
try body
375375
finally inEnum = saved
376376
}
@@ -1586,7 +1586,7 @@ object Parsers {
15861586
case parent :: Nil if in.token != LBRACE =>
15871587
reposition(if (parent.isType) ensureApplied(wrapNew(parent)) else parent)
15881588
case _ =>
1589-
New(reposition(templateBodyOpt(emptyConstructor, parents, Nil, isEnum = false)))
1589+
New(reposition(templateBodyOpt(emptyConstructor, parents, Nil)))
15901590
}
15911591
}
15921592

@@ -2555,12 +2555,7 @@ object Parsers {
25552555
val modName = ident()
25562556
val clsName = modName.toTypeName
25572557
val constr = classConstr()
2558-
val templ = templateOpt(constr, isEnum = true)
2559-
templ match {
2560-
case Template(_, _, _, List(EmptyTree)) =>
2561-
syntaxError("enum body should not be empty.", start)
2562-
case _ =>
2563-
}
2558+
val templ = template(constr, isEnum = true)
25642559
finalizeDef(TypeDef(clsName, templ), addMod(mods, enumMod), start)
25652560
}
25662561

@@ -2633,7 +2628,7 @@ object Parsers {
26332628
val tparams1 = tparams.map(tparam => tparam.withMods(tparam.mods | PrivateLocal))
26342629
val vparamss1 = vparamss.map(_.map(vparam =>
26352630
vparam.withMods(vparam.mods &~ Param | ParamAccessor | PrivateLocal)))
2636-
val templ = templateBodyOpt(makeConstructor(tparams1, vparamss1), parents, Nil, isEnum = false)
2631+
val templ = templateBodyOpt(makeConstructor(tparams1, vparamss1), parents, Nil)
26372632
if (tparams.isEmpty && vparamss.isEmpty) ModuleDef(name, templ)
26382633
else TypeDef(name.toTypeName, templ)
26392634
}
@@ -2696,26 +2691,28 @@ object Parsers {
26962691
def template(constr: DefDef, isEnum: Boolean = false): Template = {
26972692
val (parents, derived) = inheritClauses()
26982693
newLineOptWhenFollowedBy(LBRACE)
2699-
if (isEnum && in.token != LBRACE)
2700-
syntaxErrorOrIncomplete(ExpectedTokenButFound(LBRACE, in.token))
2701-
templateBodyOpt(constr, parents, derived, isEnum)
2694+
if (isEnum) {
2695+
val (self, stats) = withinEnum(templateBody())
2696+
Template(constr, parents, derived, self, stats)
2697+
}
2698+
else templateBodyOpt(constr, parents, derived)
27022699
}
27032700

27042701
/** TemplateOpt = [Template]
27052702
*/
2706-
def templateOpt(constr: DefDef, isEnum: Boolean = false): Template = {
2703+
def templateOpt(constr: DefDef): Template = {
27072704
newLineOptWhenFollowedBy(LBRACE)
27082705
if (in.token == EXTENDS || isIdent(nme.derives) || in.token == LBRACE)
2709-
template(constr, isEnum)
2706+
template(constr)
27102707
else
27112708
Template(constr, Nil, Nil, EmptyValDef, Nil)
27122709
}
27132710

27142711
/** TemplateBody ::= [nl] `{' TemplateStatSeq `}'
27152712
*/
2716-
def templateBodyOpt(constr: DefDef, parents: List[Tree], derived: List[Tree], isEnum: Boolean): Template = {
2713+
def templateBodyOpt(constr: DefDef, parents: List[Tree], derived: List[Tree]): Template = {
27172714
val (self, stats) =
2718-
if (in.token == LBRACE) withinEnum(isEnum)(templateBody()) else (EmptyValDef, Nil)
2715+
if (in.token == LBRACE) templateBody() else (EmptyValDef, Nil)
27192716
Template(constr, parents, derived, self, stats)
27202717
}
27212718

tests/neg/i5015.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,6 @@
1-
enum A extends AnyRef { } // error
1+
enum A extends AnyRef { } // error: missing case
2+
3+
enum B { def foo = 1 } // error: missing case
4+
5+
enum C // error: missing case
6+
// error: '{' expected, but eof found

0 commit comments

Comments
 (0)