Skip to content

Commit

Permalink
Merge pull request #9558 from smarter/case-pattern-binding
Browse files Browse the repository at this point in the history
Support `case` in pattern bindings under -Xsource:3
  • Loading branch information
lrytz committed Apr 20, 2021
2 parents d23bf26 + 09b5ded commit 87b0c70
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 1 deletion.
8 changes: 7 additions & 1 deletion src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
Expand Up @@ -1932,6 +1932,12 @@ self =>
*/
def generator(eqOK: Boolean, allowNestedIf: Boolean = true): List[Tree] = {
val start = in.offset
val hasCase = in.token == CASE
if (hasCase) {
if (!currentRun.isScala3) syntaxError(in.offset, s"`case` keyword in for comprehension requires the -Xsource:3 flag.")
in.skipCASE()
}

val hasVal = in.token == VAL
if (hasVal)
in.nextToken()
Expand All @@ -1950,7 +1956,7 @@ self =>
else syntaxError(in.offset, msg("unsupported", "just remove `val`"))
}

if (hasEq && eqOK) in.nextToken()
if (hasEq && eqOK && !hasCase) in.nextToken()
else accept(LARROW)
val rhs = expr()

Expand Down
10 changes: 10 additions & 0 deletions src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
Expand Up @@ -393,6 +393,16 @@ trait Scanners extends ScannersCommon {
case _ =>
}

/** Advance beyond a case token without marking the CASE in sepRegions.
* This method should be called to skip beyond CASE tokens that are
* not part of matches, i.e. no ARROW is expected after them.
*/
def skipCASE(): Unit = {
assert(token == CASE, s"Internal error: skipCASE() called on non-case token $token")
nextToken()
sepRegions = sepRegions.tail
}

/** Produce next token, filling TokenData fields of Scanner.
*/
def nextToken(): Unit = {
Expand Down
7 changes: 7 additions & 0 deletions test/files/neg/for-comprehension-case-future.check
@@ -0,0 +1,7 @@
for-comprehension-case-future.scala:22: error: '<-' expected but '=' found.
case y = x + 1
^
for-comprehension-case-future.scala:23: error: illegal start of simple expression
} yield x + y
^
2 errors
24 changes: 24 additions & 0 deletions test/files/neg/for-comprehension-case-future.scala
@@ -0,0 +1,24 @@
// scalac: -Xsource:3
//
class A {
// ok
val a =
for {
case Some(x) <- List(Some(1), None)
y = x + 1
} yield x + y

// ok
val b =
for {
Some(x) <- List(Some(1), None)
Some(y) <- List(None, Some(2))
} yield x+y

// fail
val c =
for {
case Some(x) <- List(Some(1), None)
case y = x + 1
} yield x + y
}
13 changes: 13 additions & 0 deletions test/files/neg/for-comprehension-case.check
@@ -0,0 +1,13 @@
for-comprehension-case.scala:5: error: `case` keyword in for comprehension requires the -Xsource:3 flag.
case Some(x) <- List(Some(1), None)
^
for-comprehension-case.scala:12: error: `case` keyword in for comprehension requires the -Xsource:3 flag.
case y = x + 1
^
for-comprehension-case.scala:12: error: '<-' expected but '=' found.
case y = x + 1
^
for-comprehension-case.scala:13: error: illegal start of simple expression
} yield x+y
^
4 errors
14 changes: 14 additions & 0 deletions test/files/neg/for-comprehension-case.scala
@@ -0,0 +1,14 @@
class A {
// fail
val a =
for {
case Some(x) <- List(Some(1), None)
} yield x

// fail
val b =
for {
Some(x) <- List(Some(1), None)
case y = x + 1
} yield x+y
}

0 comments on commit 87b0c70

Please sign in to comment.