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

Allow case in pattern bindings even without -Xsource:3 #9721

Merged
merged 1 commit into from Aug 11, 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
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
}