diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index a340d9160150..f3035d718e39 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -2545,7 +2545,12 @@ object Parsers { def localDef(start: Int, implicitMods: Modifiers = EmptyModifiers): Tree = { var mods = defAnnotsMods(localModifierTokens) for (imod <- implicitMods.mods) mods = addMod(mods, imod) - defOrDcl(start, mods) + if (mods.is(Final)) { + // A final modifier means the local definition is "class-like". + tmplDef(start, mods) + } else { + defOrDcl(start, mods) + } } /** BlockStatSeq ::= { BlockStat semi } [ResultExpr] diff --git a/language-server/src/dotty/tools/languageserver/Memory.scala b/language-server/src/dotty/tools/languageserver/Memory.scala index 7193df0732ea..a2869614e276 100644 --- a/language-server/src/dotty/tools/languageserver/Memory.scala +++ b/language-server/src/dotty/tools/languageserver/Memory.scala @@ -37,11 +37,11 @@ object Memory { } def stats(): String = { - final val M = 2 << 20 + val M = 2 << 20 val runtime = Runtime.getRuntime def total = runtime.totalMemory / M def maximal = runtime.maxMemory / M def free = runtime.freeMemory / M s"total used memory: $total MB, free: $free MB, maximal available = $maximal MB" } -} \ No newline at end of file +} diff --git a/tests/neg/t4815.scala b/tests/neg/t4815.scala new file mode 100644 index 000000000000..f447e896674c --- /dev/null +++ b/tests/neg/t4815.scala @@ -0,0 +1,26 @@ +class Test { + def foo = { + final def bar = 1 // error: local def may not be final + final val v = 42 // error: local val may not be final + final var v2 = 100 // error: local var may not be final + final type T = Int // error: local type def may not be final + } + + { + final def foo(x: Int) = x // error: local def may not be final + } + + final def foo2(x: Int) = x // ok: final allowed in class field + + object Foo { + final def foo(x: Int) = x // ok, but redundant + } + + abstract class Bar { + def foo: Int + } + + val x = new Bar { + override final def foo = 42 // ok: def is a field + } +} diff --git a/tests/run/tasty-eval/quoted_2.scala b/tests/run/tasty-eval/quoted_2.scala index 208bcca87708..ac3adbcc9bcd 100644 --- a/tests/run/tasty-eval/quoted_2.scala +++ b/tests/run/tasty-eval/quoted_2.scala @@ -2,10 +2,11 @@ import Macros._ object Test { + final val y = 5 + def main(args: Array[String]): Unit = { println(foo(1)) // "Some(1)" println(foo(1 + 7)) // "Some(8)" - final val y = 5 println(foo(y)) // "Some(5)" println(foo(y + 1)) val x = 4