From e236cdd7766263da8e8633beaf46bb24bc85229d Mon Sep 17 00:00:00 2001 From: i10416 Date: Mon, 22 Jan 2024 00:04:52 +0900 Subject: [PATCH 1/2] 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` From 09abbd6d54dbaa68d626c6b24366eb7a29633e84 Mon Sep 17 00:00:00 2001 From: i10416 Date: Tue, 23 Jan 2024 04:30:36 +0900 Subject: [PATCH 2/2] chore(style): fix indent --- tests/neg/i15784.check | 16 ++++++++-------- tests/neg/i15784.scala | 6 +++--- tests/pos/i15784.scala | 10 +++++----- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/neg/i15784.check b/tests/neg/i15784.check index fea28b92814c..c1540b33d956 100644 --- a/tests/neg/i15784.check +++ b/tests/neg/i15784.check @@ -1,12 +1,12 @@ --- [E006] Not Found Error: tests/neg/i15784.scala:2:26 ----------------------------------------------------------------- -2 | case List(_, Rest @ `a`) => Rest // error - | ^^^ - | Not found: a +-- [E006] Not Found Error: tests/neg/i15784.scala:2:22 ----------------------------------------------------------------- +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 +-- [E006] Not Found Error: tests/neg/i15784.scala:3:22 ----------------------------------------------------------------- +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 index aacd6a2b7837..a58a27fb3cfa 100644 --- a/tests/neg/i15784.scala +++ b/tests/neg/i15784.scala @@ -1,4 +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 + 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 index 281e54ef4da5..ab4b82638a42 100644 --- a/tests/pos/i15784.scala +++ b/tests/pos/i15784.scala @@ -1,8 +1,8 @@ def i15784 = List(42) match - case List(_, rest @ _*) => rest - case List(_, Rest @ _*) => Rest - case List(_, `Rest` @ _*) => Rest - case _ => ??? + case List(_, rest @ _*) => rest + case List(_, Rest @ _*) => Rest + case List(_, `Rest` @ _*) => Rest + case _ => ??? def i15784_auxiliary = 42 match - case `type` : Int => `type` + case `type` : Int => `type`