diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index e28ba5fd669e..d06d91d99901 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -4560,6 +4560,7 @@ object Parsers { for (imod <- implicitMods.mods) mods = addMod(mods, imod) if (mods.is(Final)) // A final modifier means the local definition is "class-like". // FIXME: Deal with modifiers separately + if isDclIntro && in.token != GIVEN then syntaxError(FinalLocalDef()) tmplDef(start, mods) else defOrDcl(start, mods) diff --git a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala index 0e42629773cc..e1994e6fcec1 100644 --- a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala +++ b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala @@ -212,6 +212,7 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe case ContextBoundCompanionNotValueID // errorNumber: 196 case InlinedAnonClassWarningID // errorNumber: 197 case UnusedSymbolID // errorNumber: 198 + case FinalLocalDefID // errorNumber: 199 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 4cc41a777fd1..e51bb97b176b 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -1850,6 +1850,12 @@ class ExpectedStartOfTopLevelDefinition()(using Context) i"You have to provide either ${hl("class")}, ${hl("trait")}, ${hl("object")}, or ${hl("enum")} definitions after modifiers" } +class FinalLocalDef()(using Context) + extends SyntaxMsg(FinalLocalDefID) { + def msg(using Context) = i"The ${hl("final")} modifier is not allowed on local definitions" + def explain(using Context) = "" +} + class NoReturnFromInlineable(owner: Symbol)(using Context) extends SyntaxMsg(NoReturnFromInlineableID) { def msg(using Context) = i"No explicit ${hl("return")} allowed from inlineable $owner" diff --git a/tests/neg/17579.check b/tests/neg/17579.check new file mode 100644 index 000000000000..1dc645a748f2 --- /dev/null +++ b/tests/neg/17579.check @@ -0,0 +1,26 @@ +-- [E199] Syntax Error: tests/neg/17579.scala:4:10 --------------------------------------------------------------------- +4 | final val v1 = 42 // error + | ^^^ + | The final modifier is not allowed on local definitions +-- [E199] Syntax Error: tests/neg/17579.scala:5:15 --------------------------------------------------------------------- +5 | final lazy val v2 = 42 // error + | ^^^ + | The final modifier is not allowed on local definitions +-- [E088] Syntax Error: tests/neg/17579.scala:6:10 --------------------------------------------------------------------- +6 | final private val v3 = 42 // error + | ^^^^^^^ + | Expected start of definition + | + | longer explanation available when compiling with `-explain` +-- [E199] Syntax Error: tests/neg/17579.scala:7:10 --------------------------------------------------------------------- +7 | final def v4 = 42 // error + | ^^^ + | The final modifier is not allowed on local definitions +-- [E199] Syntax Error: tests/neg/17579.scala:8:10 --------------------------------------------------------------------- +8 | final var v5 = 42 // error + | ^^^ + | The final modifier is not allowed on local definitions +-- [E199] Syntax Error: tests/neg/17579.scala:9:10 --------------------------------------------------------------------- +9 | final type Foo = String // error + | ^^^^ + | The final modifier is not allowed on local definitions diff --git a/tests/neg/17579.scala b/tests/neg/17579.scala new file mode 100644 index 000000000000..9860916ab979 --- /dev/null +++ b/tests/neg/17579.scala @@ -0,0 +1,10 @@ +class C: + final var v = 42 // ok + def f = + final val v1 = 42 // error + final lazy val v2 = 42 // error + final private val v3 = 42 // error + final def v4 = 42 // error + final var v5 = 42 // error + final type Foo = String // error + final given String = ???