Skip to content

Commit 217e8dc

Browse files
committed
Use p* for vararg patterns
1 parent 4a6ec60 commit 217e8dc

File tree

8 files changed

+58
-71
lines changed

8 files changed

+58
-71
lines changed

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,7 +1524,7 @@ object Parsers {
15241524

15251525
/** Is current ident a `*`, and is it followed by a `)` or `,`? */
15261526
def isPostfixStar: Boolean =
1527-
in.name == nme.raw.STAR && {
1527+
in.isIdent(nme.raw.STAR) && {
15281528
val nxt = in.lookahead.token
15291529
nxt == RPAREN || nxt == COMMA
15301530
}
@@ -2610,37 +2610,43 @@ object Parsers {
26102610
ascription(p, location)
26112611
else p
26122612

2613-
/** Pattern2 ::= [id `as'] InfixPattern
2613+
/** Pattern2 ::= InfixPattern [‘*’]
26142614
*/
2615-
val pattern2: () => Tree = () => infixPattern() match {
2615+
def pattern3(): Tree =
2616+
val p = infixPattern()
2617+
if isPostfixStar then
2618+
atSpan(in.skipToken()) {
2619+
Typed(p, Ident(tpnme.WILDCARD_STAR))
2620+
}
2621+
else p
2622+
2623+
/** Pattern2 ::= [id `@'] Pattern3
2624+
*/
2625+
val pattern2: () => Tree = () => pattern3() match
26162626
case p @ Ident(name) if in.token == AT =>
26172627
val offset = in.skipToken()
2618-
infixPattern() match {
2619-
case pt @ Ident(tpnme.WILDCARD_STAR) => // compatibility for Scala2 `x @ _*` syntax
2620-
warnMigration(p)
2621-
atSpan(startOffset(p), offset) { Typed(p, pt) }
2628+
pattern3() match {
26222629
case pt @ Bind(nme.WILDCARD, pt1: Typed) if pt.mods.is(Given) =>
26232630
atSpan(startOffset(p), 0) { Bind(name, pt1).withMods(pt.mods) }
2631+
case Typed(Ident(nme.WILDCARD), pt @ Ident(tpnme.WILDCARD_STAR)) =>
2632+
atSpan(startOffset(p), 0) { Typed(p, pt) }
26242633
case pt =>
26252634
atSpan(startOffset(p), 0) { Bind(name, pt) }
26262635
}
2627-
case p @ Ident(tpnme.WILDCARD_STAR) =>
2628-
warnMigration(p)
2629-
atSpan(startOffset(p)) { Typed(Ident(nme.WILDCARD), p) }
26302636
case p =>
26312637
p
2632-
}
26332638

2634-
private def warnMigration(p: Tree) =
2639+
private def warnStarMigration(p: Tree) =
26352640
if sourceVersion.isAtLeast(`3.1`) then
26362641
report.errorOrMigrationWarning(
2637-
"The syntax `x @ _*` is no longer supported; use `x : _*` instead",
2642+
em"The syntax `x: _*` is no longer supported for vararg splices; use `x*` instead",
26382643
in.sourcePos(startOffset(p)))
26392644

26402645
/** InfixPattern ::= SimplePattern {id [nl] SimplePattern}
26412646
*/
26422647
def infixPattern(): Tree =
2643-
infixOps(simplePattern(), in.canStartExprTokens, simplePattern, isOperator = in.name != nme.raw.BAR)
2648+
infixOps(simplePattern(), in.canStartExprTokens, simplePattern,
2649+
isOperator = in.name != nme.raw.BAR && !isPostfixStar)
26442650

26452651
/** SimplePattern ::= PatVar
26462652
* | Literal
@@ -2659,16 +2665,7 @@ object Parsers {
26592665
case id @ Ident(nme.raw.MINUS) if isNumericLit => literal(startOffset(id))
26602666
case t => simplePatternRest(t)
26612667
case USCORE =>
2662-
val wildIdent = wildcardIdent()
2663-
2664-
// compatibility for Scala2 `x @ _*` and `_*` syntax
2665-
// `x: _*' is parsed in `ascription'
2666-
if (isIdent(nme.raw.STAR)) {
2667-
in.nextToken()
2668-
if (in.token != RPAREN) syntaxError(SeqWildcardPatternPos(), wildIdent.span)
2669-
atSpan(wildIdent.span) { Ident(tpnme.WILDCARD_STAR) }
2670-
}
2671-
else wildIdent
2668+
wildcardIdent()
26722669
case LPAREN =>
26732670
atSpan(in.offset) { makeTupleOrParens(inParens(patternsOpt())) }
26742671
case QUOTE =>
@@ -2710,7 +2707,7 @@ object Parsers {
27102707
if (in.token == RPAREN) Nil else patterns(location)
27112708

27122709
/** ArgumentPatterns ::= ‘(’ [Patterns] ‘)’
2713-
* | ‘(’ [Patterns ‘,’] Pattern2 ‘:’ ‘_’ ‘*’ ‘)’
2710+
* | ‘(’ [Patterns ‘,’] Pattern2 ‘*’ ‘)’
27142711
*/
27152712
def argumentPatterns(): List[Tree] =
27162713
inParens(patternsOpt(Location.InPatternArgs))

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -415,10 +415,20 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
415415
}
416416
case Typed(expr, tpt) =>
417417
changePrec(InfixPrec) {
418-
val exprText = toText(expr)
419-
val line = exprText.lastLine
420-
val colon = if (!line.isEmpty && isOperatorPart(line.last)) " :" else ":"
421-
exprText ~ colon ~ toText(tpt) }
418+
if isWildcardStarArg(tree) then
419+
expr match
420+
case Ident(nme.WILDCARD_STAR) =>
421+
// `_*` is used as a wildcard name to indicate a vararg splice pattern;
422+
// avoid the double `*` in this case.
423+
toText(expr)
424+
case _ =>
425+
toText(expr) ~ "*"
426+
else
427+
val exprText = toText(expr)
428+
val line = exprText.lastLine
429+
val colon = if !line.isEmpty && isOperatorPart(line.last) then " :" else ":"
430+
exprText ~ colon ~ toText(tpt)
431+
}
422432
case NamedArg(name, arg) =>
423433
toText(name) ~ " = " ~ toText(arg)
424434
case Assign(lhs, rhs) =>

docs/docs/internals/syntax.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ ExprsInParens ::= ExprInParens {‘,’ ExprInParens}
252252
ExprInParens ::= PostfixExpr ‘:’ Type -- normal Expr allows only RefinedType here
253253
| Expr
254254
ParArgumentExprs ::= ‘(’ [‘using’] ExprsInParens ‘)’ exprs
255-
| ‘(’ [ExprsInParens ‘,’] PostfixExpr ‘:’ ‘_’ ‘*’ ‘)’ exprs :+ Typed(expr, Ident(wildcardStar))
255+
| ‘(’ [ExprsInParens ‘,’] PostfixExpr ‘*’ ‘)’ exprs :+ Typed(expr, Ident(wildcardStar))
256256
ArgumentExprs ::= ParArgumentExprs
257257
| BlockExpr
258258
BlockExpr ::= <<< (CaseClauses | Block) >>>
@@ -297,7 +297,7 @@ PatVar ::= varid
297297
| ‘_’
298298
Patterns ::= Pattern {‘,’ Pattern}
299299
ArgumentPatterns ::= ‘(’ [Patterns] ‘)’ Apply(fn, pats)
300-
| ‘(’ [Patterns ‘,’] Pattern2 ‘:’ ‘_’ ‘*’ ‘)’
300+
| ‘(’ [Patterns ‘,’] Pattern2 ‘*’ ‘)’
301301
```
302302

303303
### Type and Value Parameters

docs/docs/reference/syntax.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ ExprsInParens ::= ExprInParens {‘,’ ExprInParens}
248248
ExprInParens ::= PostfixExpr ‘:’ Type
249249
| Expr
250250
ParArgumentExprs ::= ‘(’ [‘using’] ExprsInParens ‘)’
251-
| ‘(’ [ExprsInParens ‘,’] PostfixExpr ‘:’ ‘_’ ‘*’ ‘)’
251+
| ‘(’ [ExprsInParens ‘,’] PostfixExpr ‘*’ ‘)’
252252
ArgumentExprs ::= ParArgumentExprs
253253
| BlockExpr
254254
BlockExpr ::= <<< (CaseClauses | Block) >>>
@@ -277,7 +277,7 @@ TypeCaseClause ::= ‘case’ InfixType ‘=>’ Type [nl]
277277
278278
Pattern ::= Pattern1 { ‘|’ Pattern1 }
279279
Pattern1 ::= Pattern2 [‘:’ RefinedType]
280-
Pattern2 ::= [id ‘@’] InfixPattern
280+
Pattern2 ::= [id ‘@’] InfixPattern [‘*’]
281281
InfixPattern ::= SimplePattern { id [nl] SimplePattern }
282282
SimplePattern ::= PatVar
283283
| Literal
@@ -291,7 +291,7 @@ PatVar ::= varid
291291
| ‘_’
292292
Patterns ::= Pattern {‘,’ Pattern}
293293
ArgumentPatterns ::= ‘(’ [Patterns] ‘)’
294-
| ‘(’ [Patterns ‘,’] Pattern2 ‘:’ ‘_’ ‘*’ ‘)’
294+
| ‘(’ [Patterns ‘,’] Pattern2 ‘*’ ‘)’
295295
```
296296

297297
### Type and Value Parameters

tests/invalid/pos/t3577.scala

Lines changed: 0 additions & 32 deletions
This file was deleted.

tests/neg/t5702-neg-bad-and-wild.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ object Test {
77
val is = List(1,2,3)
88

99
is match {
10-
case List(1, _*,) => // error // error // error: bad use of _* (a sequence pattern must be the last pattern)
10+
case List(1, _*,) => // error // // error: bad use of _* (a sequence pattern must be the last pattern)
1111
// illegal start of simple pattern
12-
case List(1, _*3,) => // error // error: illegal start of simple pattern
12+
case List(1, _*3,) => // error // error // error: illegal start of simple pattern
1313
//case List(1, _*3:) => // poor recovery by parens
14-
case List(1, x*) => // error: use _* to match a sequence
15-
case List(x*, 1) => // error: trailing * is not a valid pattern
16-
case (1, x*) => // error: trailing * is not a valid pattern
14+
case List(1, x*) => // ok
15+
case List(x*, 1) => //ok
16+
case (1, x*) => //ok
1717
case (1, x: _*) => // error: bad use of _* (sequence pattern not allowed)
1818
}
1919

File renamed without changes.

tests/pos/t3577.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
case class Check[A](val value: A)
2+
3+
case class C2(checks: Check[_]*);
4+
5+
object C {
6+
def m(x : C2): Any = (null: Any) match {
7+
case C2(_, rest*) => {
8+
rest.map(_.value)
9+
}
10+
}
11+
}
12+

0 commit comments

Comments
 (0)