diff --git a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala index ff0aac879752..c3cad8cbfea5 100644 --- a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala +++ b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala @@ -216,6 +216,10 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe case FinalLocalDefID // errorNumber: 200 case NonNamedArgumentInJavaAnnotationID // errorNumber: 201 - unused in LTS case QuotedTypeMissingID // errorNumber: 202 + case DeprecatedAssignmentSyntaxID // errorNumber: 203 + case DeprecatedInfixNamedArgumentSyntaxID // errorNumber: 204 + case GivenSearchPriorityID // errorNumber: 205 + case EnumMayNotBeValueClassesID // errorNumber: 206 def errorNumber = ordinal - 1 diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index de59c21896b6..8acf237e8e7c 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -1812,12 +1812,12 @@ class NotAPath(tp: Type, usage: String)(using Context) extends TypeMsg(NotAPathI if sym.isAllOf(Flags.InlineParam) then i""" |Inline parameters are not considered immutable paths and cannot be used as - |singleton types. - | + |singleton types. + | |Hint: Removing the `inline` qualifier from the `${sym.name}` parameter |may help resolve this issue.""" else "" - + class WrongNumberOfParameters(tree: untpd.Tree, foundCount: Int, pt: Type, expectedCount: Int)(using Context) extends SyntaxMsg(WrongNumberOfParametersID) { @@ -3173,15 +3173,21 @@ final class QuotedTypeMissing(tpe: Type)(using Context) extends StagingMessage(Q private def witness = defn.QuotedTypeClass.typeRef.appliedTo(tpe) - override protected def msg(using Context): String = + override protected def msg(using Context): String = i"Reference to $tpe within quotes requires a given ${witness} in scope" override protected def explain(using Context): String = - i"""Referencing `$tpe` inside a quoted expression requires a `${witness}` to be in scope. + i"""Referencing `$tpe` inside a quoted expression requires a `${witness}` to be in scope. |Since Scala is subject to erasure at runtime, the type information will be missing during the execution of the code. - |`${witness}` is therefore needed to carry `$tpe`'s type information into the quoted code. - |Without an implicit `${witness}`, the type `$tpe` cannot be properly referenced within the expression. + |`${witness}` is therefore needed to carry `$tpe`'s type information into the quoted code. + |Without an implicit `${witness}`, the type `$tpe` cannot be properly referenced within the expression. |To resolve this, ensure that a `${witness}` is available, either through a context-bound or explicitly. |""" end QuotedTypeMissing + +final class EnumMayNotBeValueClasses(sym: Symbol)(using Context) extends SyntaxMsg(EnumMayNotBeValueClassesID): + def msg(using Context): String = i"$sym may not be a value class" + + def explain(using Context) = "" +end EnumMayNotBeValueClasses diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index cd00ca9340c6..bf99def353b0 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -715,11 +715,16 @@ object Checking { case _ => report.error(ValueClassesMayNotContainInitalization(clazz), stat.srcPos) } - if (clazz.isDerivedValueClass) { + // We don't check synthesised enum anonymous classes that are generated from + // enum extending a value class type (AnyVal or an alias of it) + // The error message 'EnumMayNotBeValueClassesID' will take care of generating the error message (See #22236) + if (clazz.isDerivedValueClass && !clazz.isEnumAnonymClass) { if (clazz.is(Trait)) report.error(CannotExtendAnyVal(clazz), clazz.srcPos) if clazz.is(Module) then report.error(CannotExtendAnyVal(clazz), clazz.srcPos) + if (clazz.is(Enum)) + report.error(EnumMayNotBeValueClasses(clazz), clazz.srcPos) if (clazz.is(Abstract)) report.error(ValueClassesMayNotBeAbstract(clazz), clazz.srcPos) if (!clazz.isStatic) diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index c1a6861102fb..d98790b89600 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -1581,7 +1581,8 @@ class Namer { typer: Typer => } else { val pclazz = pt.typeSymbol - if pclazz.is(Final) then + // The second condition avoids generating a useless message (See #22236 for more details) + if pclazz.is(Final) && !(pclazz.is(Enum) && pclazz.isDerivedValueClass) then report.error(ExtendFinalClass(cls, pclazz), cls.srcPos) else if pclazz.isEffectivelySealed && pclazz.associatedFile != cls.associatedFile then if pclazz.is(Sealed) && !pclazz.is(JavaDefined) then diff --git a/tests/neg/i21944.check b/tests/neg/i21944.check new file mode 100644 index 000000000000..591447c6a510 --- /dev/null +++ b/tests/neg/i21944.check @@ -0,0 +1,4 @@ +-- [E206] Syntax Error: tests/neg/i21944.scala:1:5 --------------------------------------------------------------------- +1 |enum Orientation extends AnyVal: // error + | ^ + | class Orientation may not be a value class diff --git a/tests/neg/i21944.scala b/tests/neg/i21944.scala new file mode 100644 index 000000000000..bf335e56c671 --- /dev/null +++ b/tests/neg/i21944.scala @@ -0,0 +1,2 @@ +enum Orientation extends AnyVal: // error + case North, South, East, West