Skip to content

Commit 9be10ed

Browse files
committed
Allow case in pattern bindings even without -Xsource:3
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.
1 parent f9acc3d commit 9be10ed

7 files changed

+30
-55
lines changed

spec/06-expressions.md

+11-5
Original file line numberDiff line numberDiff line change
@@ -912,7 +912,7 @@ A semicolon preceding the `while` symbol of a do loop expression is ignored.
912912
Expr1 ::= ‘for’ (‘(’ Enumerators ‘)’ | ‘{’ Enumerators ‘}’)
913913
{nl} [‘yield’] Expr
914914
Enumerators ::= Generator {semi Generator}
915-
Generator ::= Pattern1 ‘<-’ Expr {[semi] Guard | semi Pattern1 ‘=’ Expr}
915+
Generator ::= [‘case’] Pattern1 ‘<-’ Expr {[semi] Guard | semi Pattern1 ‘=’ Expr}
916916
Guard ::= ‘if’ PostfixExpr
917917
```
918918

@@ -922,9 +922,15 @@ A _for comprehension_ `for ($\mathit{enums}\,$) yield $e$` evaluates
922922
expression $e$ for each binding generated by the enumerators $\mathit{enums}$
923923
and collects the results. An enumerator sequence always starts with a
924924
generator; this can be followed by further generators, value
925-
definitions, or guards. A _generator_ `$p$ <- $e$`
926-
produces bindings from an expression $e$ which is matched in some way
927-
against pattern $p$. A _value definition_ `$p$ = $e$`
925+
definitions, or guards.
926+
927+
A _generator_ `$p$ <- $e$` produces bindings from an expression $e$ which is
928+
matched in some way against pattern $p$. Optionally, `case` can appear in front
929+
of a generator pattern, this has no meaning in Scala 2 but will be [required in
930+
Scala 3 if `p` is not
931+
irrefutable](https://docs.scala-lang.org/scala3/reference/changed-features/pattern-bindings.html).
932+
933+
A _value definition_ `$p$ = $e$`
928934
binds the value name $p$ (or several names in a pattern $p$) to
929935
the result of evaluating the expression $e$. A _guard_
930936
`if $e$` contains a boolean expression which restricts
@@ -1762,4 +1768,4 @@ Finally:
17621768

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

1765-
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.
1771+
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.

spec/13-syntax-summary.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ grammar:
172172
| (Bindings | ([‘implicit’] id | ‘_’) ‘:’ CompoundType) ‘=>’ Block
173173
174174
Enumerators ::= Generator {semi Generator}
175-
Generator ::= Pattern1 ‘<-’ Expr {[semi] Guard | semi Pattern1 ‘=’ Expr}
175+
Generator ::= [‘case’] Pattern1 ‘<-’ Expr {[semi] Guard | semi Pattern1 ‘=’ Expr}
176176
177177
CaseClauses ::= CaseClause { CaseClause }
178178
CaseClause ::= ‘case’ Pattern [Guard] ‘=>’ Block

src/compiler/scala/tools/nsc/ast/parser/Parsers.scala

+2-4
Original file line numberDiff line numberDiff line change
@@ -1915,16 +1915,14 @@ self =>
19151915
else generator(!isFirst, allowNestedIf)
19161916

19171917
/** {{{
1918-
* Generator ::= Pattern1 (`<-' | `=') Expr [Guard]
1918+
* Generator ::= [`case'] Pattern1 (`<-' | `=') Expr [Guard]
19191919
* }}}
19201920
*/
19211921
def generator(eqOK: Boolean, allowNestedIf: Boolean = true): List[Tree] = {
19221922
val start = in.offset
19231923
val hasCase = in.token == CASE
1924-
if (hasCase) {
1925-
if (!currentRun.isScala3) syntaxError(in.offset, s"`case` keyword in for comprehension requires the -Xsource:3 flag.")
1924+
if (hasCase)
19261925
in.skipCASE()
1927-
}
19281926

19291927
val hasVal = in.token == VAL
19301928
if (hasVal)

test/files/neg/for-comprehension-case-future.check

-7
This file was deleted.

test/files/neg/for-comprehension-case-future.scala

-24
This file was deleted.
+4-10
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
1-
for-comprehension-case.scala:5: error: `case` keyword in for comprehension requires the -Xsource:3 flag.
2-
case Some(x) <- List(Some(1), None)
3-
^
4-
for-comprehension-case.scala:12: error: `case` keyword in for comprehension requires the -Xsource:3 flag.
5-
case y = x + 1
6-
^
7-
for-comprehension-case.scala:12: error: '<-' expected but '=' found.
1+
for-comprehension-case.scala:20: error: '<-' expected but '=' found.
82
case y = x + 1
93
^
10-
for-comprehension-case.scala:13: error: illegal start of simple expression
11-
} yield x+y
4+
for-comprehension-case.scala:21: error: illegal start of simple expression
5+
} yield x + y
126
^
13-
four errors found
7+
two errors found
+12-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
class A {
2-
// fail
2+
// ok
33
val a =
44
for {
55
case Some(x) <- List(Some(1), None)
6-
} yield x
6+
y = x + 1
7+
} yield x + y
78

8-
// fail
9+
// ok
910
val b =
1011
for {
1112
Some(x) <- List(Some(1), None)
12-
case y = x + 1
13+
Some(y) <- List(None, Some(2))
1314
} yield x+y
15+
16+
// fail
17+
val c =
18+
for {
19+
case Some(x) <- List(Some(1), None)
20+
case y = x + 1
21+
} yield x + y
1422
}

0 commit comments

Comments
 (0)