Skip to content

Commit

Permalink
better explain message for 'pattern expected' (#18753)
Browse files Browse the repository at this point in the history
  • Loading branch information
bishabosha authored Oct 24, 2023
2 parents 64134b3 + 721dcad commit 15033c7
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 25 deletions.
47 changes: 22 additions & 25 deletions compiler/src/dotty/tools/dotc/reporting/messages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -973,66 +973,63 @@ extends SyntaxMsg(IllegalStartOfSimplePatternID) {
def msg(using Context) = "pattern expected"
def explain(using Context) = {
val sipCode =
"""def f(x: Int, y: Int) = x match {
| case `y` => ...
|}
"""
"""def f(x: Int, y: Int) = x match
| case `y` => ...""".stripMargin
val constructorPatternsCode =
"""case class Person(name: String, age: Int)
|
|def test(p: Person) = p match {
| case Person(name, age) => ...
|}
"""
val tupplePatternsCode =
"""def swap(tuple: (String, Int)): (Int, String) = tuple match {
| case (text, number) => (number, text)
|}
"""
| def test(p: Person) = p match
| case Person(name, age) => ...""".stripMargin
val tuplePatternsCode =
"""def swap(tuple: (String, Int)): (Int, String) = tuple match
| case (text, number) => (number, text)""".stripMargin
val patternSequencesCode =
"""def getSecondValue(list: List[Int]): Int = list match {
| case List(_, second, x:_*) => second
| case _ => 0
|}"""
"""def getSecondValue(list: List[Int]): Int = list match
| case List(_, second, x*) => second
| case _ => 0""".stripMargin
i"""|Simple patterns can be divided into several groups:
|- Variable Patterns: ${hl("case x => ...")}.
|- Variable Patterns: ${hl("case x => ...")} or ${hl("case _ => ...")}
| It matches any value, and binds the variable name to that value.
| A special case is the wild-card pattern _ which is treated as if it was a fresh
| variable on each occurrence.
|
|- Typed Patterns: ${hl("case x: Int => ...")} or ${hl("case _: Int => ...")}.
|- Typed Patterns: ${hl("case x: Int => ...")} or ${hl("case _: Int => ...")}
| This pattern matches any value matched by the specified type; it binds the variable
| name to that value.
|
|- Literal Patterns: ${hl("case 123 => ...")} or ${hl("case 'A' => ...")}.
|- Given Patterns: ${hl("case given ExecutionContext => ...")}
| This pattern matches any value matched by the specified type; it binds a ${hl("given")}
| instance with the same type to that value.
|
|- Literal Patterns: ${hl("case 123 => ...")} or ${hl("case 'A' => ...")}
| This type of pattern matches any value that is equal to the specified literal.
|
|- Stable Identifier Patterns:
|
| $sipCode
| ${hl(sipCode)}
|
| the match succeeds only if the x argument and the y argument of f are equal.
|
|- Constructor Patterns:
|
| $constructorPatternsCode
| ${hl(constructorPatternsCode)}
|
| The pattern binds all object's fields to the variable names (name and age, in this
| case).
|
|- Tuple Patterns:
|
| $tupplePatternsCode
| ${hl(tuplePatternsCode)}
|
| Calling:
|
| ${hl("""swap(("Luftballons", 99)""")}
| ${hl("""swap(("Luftballons", 99))""")}
|
| would give ${hl("""(99, "Luftballons")""")} as a result.
|
|- Pattern Sequences:
|
| $patternSequencesCode
| ${hl(patternSequencesCode)}
|
| Calling:
|
Expand Down
68 changes: 68 additions & 0 deletions tests/neg/i18750-format.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
-- [E032] Syntax Error: tests/neg/i18750-format.scala:4:7 --------------------------------------------------------------
4 | case # => () // error
| ^
| pattern expected
|---------------------------------------------------------------------------------------------------------------------
| Explanation (enabled by `-explain`)
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| Simple patterns can be divided into several groups:
| - Variable Patterns: case x => ... or case _ => ...
| It matches any value, and binds the variable name to that value.
| A special case is the wild-card pattern _ which is treated as if it was a fresh
| variable on each occurrence.
|
| - Typed Patterns: case x: Int => ... or case _: Int => ...
| This pattern matches any value matched by the specified type; it binds the variable
| name to that value.
|
| - Given Patterns: case given ExecutionContext => ...
| This pattern matches any value matched by the specified type; it binds a given
| instance with the same type to that value.
|
| - Literal Patterns: case 123 => ... or case 'A' => ...
| This type of pattern matches any value that is equal to the specified literal.
|
| - Stable Identifier Patterns:
|
| def f(x: Int, y: Int) = x match
| case `y` => ...
|
| the match succeeds only if the x argument and the y argument of f are equal.
|
| - Constructor Patterns:
|
| case class Person(name: String, age: Int)
|
| def test(p: Person) = p match
| case Person(name, age) => ...
|
| The pattern binds all object's fields to the variable names (name and age, in this
| case).
|
| - Tuple Patterns:
|
| def swap(tuple: (String, Int)): (Int, String) = tuple match
| case (text, number) => (number, text)
|
| Calling:
|
| swap(("Luftballons", 99))
|
| would give (99, "Luftballons") as a result.
|
| - Pattern Sequences:
|
| def getSecondValue(list: List[Int]): Int = list match
| case List(_, second, x*) => second
| case _ => 0
|
| Calling:
|
| getSecondValue(List(1, 10, 2))
|
| would give 10 as a result.
| This pattern is possible because a companion object for the List class has a method
| with the following signature:
|
| def unapplySeq[A](x: List[A]): Some[List[A]]
---------------------------------------------------------------------------------------------------------------------
4 changes: 4 additions & 0 deletions tests/neg/i18750-format.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//> using options -explain

def test = 23 match
case # => () // error

0 comments on commit 15033c7

Please sign in to comment.