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 10, 2021
1 parent 164b9c5 commit 0cecad3
Show file tree
Hide file tree
Showing 7 changed files with 29 additions and 54 deletions.
14 changes: 10 additions & 4 deletions spec/06-expressions.md
Expand Up @@ -919,7 +919,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 @@ -929,9 +929,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
2 changes: 1 addition & 1 deletion spec/13-syntax-summary.md
Expand Up @@ -184,7 +184,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 @@ -1993,16 +1993,14 @@ self =>
}

/** {{{
* 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
^
4 errors
2 errors
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 0cecad3

Please sign in to comment.