Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support case in pattern bindings under -Xsource:3 #9558

Merged
merged 1 commit into from Apr 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
Expand Up @@ -1926,6 +1926,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 @@ -1944,7 +1950,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
}