Skip to content

Commit

Permalink
Fix syntax and parsing of vararg patterns
Browse files Browse the repository at this point in the history
Syntax: Remove outdated `*` after InfixPattern
Parsing: Only allow vararg `*` in ArgumentPatterns

Fixes #17443
  • Loading branch information
odersky committed Jun 25, 2023
1 parent ceca748 commit 7995bfd
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 15 deletions.
22 changes: 11 additions & 11 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1665,7 +1665,7 @@ object Parsers {
if in.token == LPAREN then funParamClause() :: funParamClauses() else Nil

/** InfixType ::= RefinedType {id [nl] RefinedType}
* | RefinedType `^`
* | RefinedType `^` // under capture checking
*/
def infixType(): Tree = infixTypeRest(refinedType())

Expand Down Expand Up @@ -2855,13 +2855,13 @@ object Parsers {
if (isIdent(nme.raw.BAR)) { in.nextToken(); pattern1(location) :: patternAlts(location) }
else Nil

/** Pattern1 ::= PatVar Ascription
* | [‘-’] integerLiteral Ascription
* | [‘-’] floatingPointLiteral Ascription
/** Pattern1 ::= PatVar `:` RefinedType
* | [‘-’] integerLiteral `:` RefinedType
* | [‘-’] floatingPointLiteral `:` RefinedType
* | Pattern2
*/
def pattern1(location: Location = Location.InPattern): Tree =
val p = pattern2()
val p = pattern2(location)
if in.isColon then
val isVariableOrNumber = isVarPattern(p) || p.isInstanceOf[Number]
if !isVariableOrNumber then
Expand All @@ -2879,11 +2879,10 @@ object Parsers {
else p

/** Pattern3 ::= InfixPattern
* | PatVar ‘*’
*/
def pattern3(): Tree =
def pattern3(location: Location): Tree =
val p = infixPattern()
if followingIsVararg() then
if location.inArgs && followingIsVararg() then
val start = in.skipToken()
p match
case p @ Ident(name) if name.isVarPattern =>
Expand All @@ -2895,10 +2894,10 @@ object Parsers {

/** Pattern2 ::= [id `@'] Pattern3
*/
val pattern2: () => Tree = () => pattern3() match
val pattern2: Location => Tree = location => pattern3(location) match
case p @ Ident(name) if in.token == AT =>
val offset = in.skipToken()
pattern3() match {
pattern3(location) match {
case pt @ Bind(nme.WILDCARD, pt1: Typed) if pt.mods.is(Given) =>
atSpan(startOffset(p), 0) { Bind(name, pt1).withMods(pt.mods) }
case Typed(Ident(nme.WILDCARD), pt @ Ident(tpnme.WILDCARD_STAR)) =>
Expand Down Expand Up @@ -2928,6 +2927,7 @@ object Parsers {
* | XmlPattern
* | `(' [Patterns] `)'
* | SimplePattern1 [TypeArgs] [ArgumentPatterns]
* | ‘given’ RefinedType
* SimplePattern1 ::= SimpleRef
* | SimplePattern1 `.' id
* PatVar ::= id
Expand Down Expand Up @@ -3569,7 +3569,7 @@ object Parsers {
* VarDcl ::= id {`,' id} `:' Type
*/
def patDefOrDcl(start: Offset, mods: Modifiers): Tree = atSpan(start, nameStart) {
val first = pattern2()
val first = pattern2(Location.InPattern)
var lhs = first match {
case id: Ident if in.token == COMMA =>
in.nextToken()
Expand Down
6 changes: 3 additions & 3 deletions docs/_docs/internals/syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ Pattern1 ::= PatVar ‘:’ RefinedType
| [‘-’] integerLiteral ‘:’ RefinedType Typed(pat, tpe)
| [‘-’] floatingPointLiteral ‘:’ RefinedType Typed(pat, tpe)
| Pattern2
Pattern2 ::= [id ‘@’] InfixPattern [‘*’] Bind(name, pat)
Pattern2 ::= [id ‘@’] InfixPattern Bind(name, pat)
InfixPattern ::= SimplePattern { id [nl] SimplePattern } InfixOp(pat, op, pat)
SimplePattern ::= PatVar Ident(wildcard)
| Literal Bind(name, Ident(wildcard))
Expand Down Expand Up @@ -357,8 +357,8 @@ ClsParam ::= {Annotation}
[{Modifier} (‘val’ | ‘var’) | ‘inline’] Param
DefParamClauses ::= DefParamClause { DefParamClause } -- and two DefTypeParamClause cannot be adjacent
DefParamClause ::= DefTypeParamClause
| DefTermParamClause
DefParamClause ::= DefTypeParamClause
| DefTermParamClause
| UsingParamClause
TypelessClauses ::= TypelessClause {TypelessClause}
TypelessClause ::= DefTermParamClause
Expand Down
2 changes: 1 addition & 1 deletion docs/_docs/reference/syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ Pattern1 ::= PatVar ‘:’ RefinedType
| [‘-’] integerLiteral ‘:’ RefinedType
| [‘-’] floatingPointLiteral ‘:’ RefinedType
| Pattern2
Pattern2 ::= [id ‘@’] InfixPattern [‘*’]
Pattern2 ::= [id ‘@’] InfixPattern
InfixPattern ::= SimplePattern { id [nl] SimplePattern }
SimplePattern ::= PatVar
| Literal
Expand Down
2 changes: 2 additions & 0 deletions tests/neg/i17443.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def run() =
val x = List(1) match { case (xs*) => xs } // error

0 comments on commit 7995bfd

Please sign in to comment.