diff --git a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala index 4dc4ec68448b..bd9e24f76dc7 100644 --- a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala +++ b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala @@ -6,6 +6,7 @@ import core._ import util.Positions._, Types._, Contexts._, Constants._, Names._, NameOps._, Flags._ import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._ import Decorators._ +import reporting.diagnostic.messages.EnumCaseDefinitionInNonEnumOwner import collection.mutable.ListBuffer import util.Property import typer.ErrorReporting._ @@ -32,7 +33,7 @@ object DesugarEnums { /** Is enum case `tree` situated in a companion object of an enum class? */ def enumCaseIsLegal(tree: Tree)(implicit ctx: Context): Boolean = ( ctx.owner.is(ModuleClass) && enumClass.derivesFrom(defn.EnumClass) - || { ctx.error(em"case not allowed here, since owner ${ctx.owner} is not an `enum' object", tree.pos) + || { ctx.error(EnumCaseDefinitionInNonEnumOwner(ctx.owner), tree.pos) false } ) diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java index 37a368b00823..ac8a45405eac 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java @@ -101,6 +101,7 @@ public enum ErrorMessageID { ReturnOutsideMethodDefinitionID, UncheckedTypePatternID, ExtendFinalClassID, + EnumCaseDefinitionInNonEnumOwnerID, ; public int errorNumber() { diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 474b07e0415a..753bb76a551b 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -1777,5 +1777,13 @@ object messages { val explanation = hl"""A class marked with the ${"final"} keyword cannot be extended""" } - + case class EnumCaseDefinitionInNonEnumOwner(owner: Symbol)(implicit ctx: Context) + extends Message(EnumCaseDefinitionInNonEnumOwnerID) { + val kind = "Syntax" + val msg = em"case not allowed here, since owner ${owner} is not an ${"enum"} object" + val explanation = + hl"""${"enum"} cases are only allowed within the companion ${"object"} of an ${"enum class"}. + |If you want to create an ${"enum"} case, make sure the corresponding ${"enum class"} exists + |and has the ${"enum"} keyword.""" + } } diff --git a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala index 2961a5c8c42f..b9846c665dba 100644 --- a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala +++ b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala @@ -998,6 +998,7 @@ class ErrorMessagesTests extends ErrorMessagesTest { val ReturnOutsideMethodDefinition(owner) :: Nil = messages assertEquals("object A", owner.show) } + @Test def extendFinalClass = checkMessagesAfter("refchecks") { """final class A | @@ -1010,4 +1011,17 @@ class ErrorMessagesTests extends ErrorMessagesTest { assertEquals(extender.show, "class B") assertEquals(parent.show, "class A") } + + @Test def enumCaseDefinitionInNonEnumOwner = + checkMessagesAfter("frontend") { + """object Qux { + | case Foo + |} + """.stripMargin + }.expect { (ictx, messages) => + implicit val ctx: Context = ictx + assertMessageCount(1, messages) + val EnumCaseDefinitionInNonEnumOwner(owner) :: Nil = messages + assertEquals("object Qux", owner.show) + } }