Skip to content

Commit

Permalink
Allow case in pattern bindings even without -Xsource:3
Browse files Browse the repository at this point in the history
In scala#9558 (which shipped with 2.13.6) we added support for `case` bindings
under -Xsource:3. Since this parser change does not break any existing
code and since IntelliJ and scalameta/metals now understand this syntax
in Scala 2 code, it should be safe to enable it by default to further
ease cross-compilation between Scala 2 and 3.
  • Loading branch information
smarter committed Aug 27, 2021
1 parent f9acc3d commit 9be10ed
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 55 deletions.
16 changes: 11 additions & 5 deletions spec/06-expressions.md
Expand Up @@ -912,7 +912,7 @@ A semicolon preceding the `while` symbol of a do loop expression is ignored.
Expr1 ::= ‘for’ (‘(’ Enumerators ‘)’ | ‘{’ Enumerators ‘}’)
{nl} [‘yield’] Expr
Enumerators ::= Generator {semi Generator}
Generator ::= Pattern1 ‘<-’ Expr {[semi] Guard | semi Pattern1 ‘=’ Expr}
Generator ::= [‘case’] Pattern1 ‘<-’ Expr {[semi] Guard | semi Pattern1 ‘=’ Expr}
Guard ::= ‘if’ PostfixExpr
```

Expand All @@ -922,9 +922,15 @@ A _for comprehension_ `for ($\mathit{enums}\,$) yield $e$` evaluates
expression $e$ for each binding generated by the enumerators $\mathit{enums}$
and collects the results. An enumerator sequence always starts with a
generator; this can be followed by further generators, value
definitions, or guards. A _generator_ `$p$ <- $e$`
produces bindings from an expression $e$ which is matched in some way
against pattern $p$. A _value definition_ `$p$ = $e$`
definitions, or guards.

A _generator_ `$p$ <- $e$` produces bindings from an expression $e$ which is
matched in some way against pattern $p$. Optionally, `case` can appear in front
of a generator pattern, this has no meaning in Scala 2 but will be [required in
Scala 3 if `p` is not
irrefutable](https://docs.scala-lang.org/scala3/reference/changed-features/pattern-bindings.html).

A _value definition_ `$p$ = $e$`
binds the value name $p$ (or several names in a pattern $p$) to
the result of evaluating the expression $e$. A _guard_
`if $e$` contains a boolean expression which restricts
Expand Down Expand Up @@ -1762,4 +1768,4 @@ Finally:

* `e.m(x) = y` becomes `e.selectDynamic("m").update(x, y)`

None of these methods are actually defined in the `scala.Dynamic`, so that users are free to define them with or without type parameters, or implicit arguments.
None of these methods are actually defined in the `scala.Dynamic`, so that users are free to define them with or without type parameters, or implicit arguments.
2 changes: 1 addition & 1 deletion spec/13-syntax-summary.md
Expand Up @@ -172,7 +172,7 @@ grammar:
| (Bindings | ([‘implicit’] id | ‘_’) ‘:’ CompoundType) ‘=>’ Block
Enumerators ::= Generator {semi Generator}
Generator ::= Pattern1 ‘<-’ Expr {[semi] Guard | semi Pattern1 ‘=’ Expr}
Generator ::= [‘case’] Pattern1 ‘<-’ Expr {[semi] Guard | semi Pattern1 ‘=’ Expr}
CaseClauses ::= CaseClause { CaseClause }
CaseClause ::= ‘case’ Pattern [Guard] ‘=>’ Block
Expand Down
6 changes: 2 additions & 4 deletions src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
Expand Up @@ -1915,16 +1915,14 @@ self =>
else generator(!isFirst, allowNestedIf)

/** {{{
* Generator ::= Pattern1 (`<-' | `=') Expr [Guard]
* Generator ::= [`case'] Pattern1 (`<-' | `=') Expr [Guard]
* }}}
*/
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.")
if (hasCase)
in.skipCASE()
}

val hasVal = in.token == VAL
if (hasVal)
Expand Down
7 changes: 0 additions & 7 deletions test/files/neg/for-comprehension-case-future.check

This file was deleted.

24 changes: 0 additions & 24 deletions test/files/neg/for-comprehension-case-future.scala

This file was deleted.

14 changes: 4 additions & 10 deletions test/files/neg/for-comprehension-case.check
@@ -1,13 +1,7 @@
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.
for-comprehension-case.scala:20: error: '<-' expected but '=' found.
case y = x + 1
^
for-comprehension-case.scala:13: error: illegal start of simple expression
} yield x+y
for-comprehension-case.scala:21: error: illegal start of simple expression
} yield x + y
^
four errors found
two errors found
16 changes: 12 additions & 4 deletions test/files/neg/for-comprehension-case.scala
@@ -1,14 +1,22 @@
class A {
// fail
// ok
val a =
for {
case Some(x) <- List(Some(1), None)
} yield x
y = x + 1
} yield x + y

// fail
// ok
val b =
for {
Some(x) <- List(Some(1), None)
case y = x + 1
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
}

0 comments on commit 9be10ed

Please sign in to comment.