From e236cdd7766263da8e8633beaf46bb24bc85229d Mon Sep 17 00:00:00 2001 From: i10416 Date: Mon, 22 Jan 2024 00:04:52 +0900 Subject: [PATCH] fix(#15784): ident rule for pat match was too strict close https://github.com/lampepfl/dotty/issues/15784 Scala 2 allows backticked identifier and capital identifier in pattern match, but Scala 3 mistakenly prohibited them. For example, the following code is valid in Scala 2, ```scala List(42) match { case List(_, Rest @ _*) => Rest case List(_, `Rest` @ _*) => `Rest` _ => ??? } ``` whereas it resulted in `Not Found Rest` error in Scala 3. This is because the condition to detect wildcard pattern was so strict that it chose the wrong match arm; `case _ => ifExpr`. --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 2 +- tests/neg/i15784.check | 12 ++++++++++++ tests/neg/i15784.scala | 4 ++++ tests/pos/i15784.scala | 8 ++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 tests/neg/i15784.check create mode 100644 tests/neg/i15784.scala create mode 100644 tests/pos/i15784.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 222640124db3..9b804d24b7e6 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -944,7 +944,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer * (x: T) to (x @ (w: T)). This is either `_` or `_*`. */ def cases(ifPat: => Tree, ifExpr: => Tree, wildName: TermName) = tree.expr match { - case id: untpd.Ident if (ctx.mode is Mode.Pattern) && untpd.isVarPattern(id) => + case id: untpd.Ident if (ctx.mode is Mode.Pattern) => if (id.name == nme.WILDCARD || id.name == nme.WILDCARD_STAR) ifPat else { import untpd.* diff --git a/tests/neg/i15784.check b/tests/neg/i15784.check new file mode 100644 index 000000000000..fea28b92814c --- /dev/null +++ b/tests/neg/i15784.check @@ -0,0 +1,12 @@ +-- [E006] Not Found Error: tests/neg/i15784.scala:2:26 ----------------------------------------------------------------- +2 | case List(_, Rest @ `a`) => Rest // error + | ^^^ + | Not found: a + | + | longer explanation available when compiling with `-explain` +-- [E006] Not Found Error: tests/neg/i15784.scala:3:26 ----------------------------------------------------------------- +3 | case List(_, Rest @ A) => Rest // error + | ^ + | Not found: A + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg/i15784.scala b/tests/neg/i15784.scala new file mode 100644 index 000000000000..aacd6a2b7837 --- /dev/null +++ b/tests/neg/i15784.scala @@ -0,0 +1,4 @@ +def i15784 = List(42) match + case List(_, Rest @ `a`) => Rest // error + case List(_, Rest @ A) => Rest // error + case _ => ??? \ No newline at end of file diff --git a/tests/pos/i15784.scala b/tests/pos/i15784.scala new file mode 100644 index 000000000000..281e54ef4da5 --- /dev/null +++ b/tests/pos/i15784.scala @@ -0,0 +1,8 @@ +def i15784 = List(42) match + case List(_, rest @ _*) => rest + case List(_, Rest @ _*) => Rest + case List(_, `Rest` @ _*) => Rest + case _ => ??? + +def i15784_auxiliary = 42 match + case `type` : Int => `type`