@@ -376,13 +376,13 @@ object Parsers {
376376 in.nextToken() // needed to ensure progress; otherwise we might cycle forever
377377 accept(SEMI )
378378
379- def rewriteNotice (additionalOption : String = " " ) = {
379+ def rewriteNotice (version : String = " 3.0 " , additionalOption : String = " " ) = {
380380 val optionStr = if (additionalOption.isEmpty) " " else " " ++ additionalOption
381- i " \n This construct can be rewritten automatically under $optionStr -rewrite -source 3.0 -migration. "
381+ i " \n This construct can be rewritten automatically under $optionStr -rewrite -source $version -migration. "
382382 }
383383
384384 def syntaxVersionError (option : String , span : Span ) =
385- syntaxError(em """ This construct is not allowed under $option. ${rewriteNotice(option)}""" , span)
385+ syntaxError(em """ This construct is not allowed under $option. ${rewriteNotice(" 3.0 " , option)}""" , span)
386386
387387 def rewriteToNewSyntax (span : Span = Span (in.offset)): Boolean = {
388388 if (in.newSyntax) {
@@ -919,7 +919,20 @@ object Parsers {
919919 val next = in.lookahead.token
920920 next == LBRACKET || next == LPAREN
921921
922- /* --------- OPERAND/OPERATOR STACK --------------------------------------- */
922+ /** Is current ident a `*`, and is it followed by a `)` or `, )`? */
923+ def followingIsVararg (): Boolean =
924+ in.isIdent(nme.raw.STAR ) && {
925+ val lookahead = in.LookaheadScanner ()
926+ lookahead.nextToken()
927+ lookahead.token == RPAREN
928+ || lookahead.token == COMMA
929+ && {
930+ lookahead.nextToken()
931+ lookahead.token == RPAREN
932+ }
933+ }
934+
935+ /* --------- OPERAND/OPERATOR STACK --------------------------------------- */
923936
924937 var opStack : List [OpInfo ] = Nil
925938
@@ -956,8 +969,8 @@ object Parsers {
956969 */
957970 def infixOps (
958971 first : Tree , canStartOperand : Token => Boolean , operand : () => Tree ,
959- isType : Boolean = false ,
960- isOperator : => Boolean = true ,
972+ isType : Boolean ,
973+ isOperator : => Boolean ,
961974 maybePostfix : Boolean = false ): Tree = {
962975 val base = opStack
963976
@@ -1522,15 +1535,9 @@ object Parsers {
15221535 */
15231536 def infixType (): Tree = infixTypeRest(refinedType())
15241537
1525- /** Is current ident a `*`, and is it followed by a `)` or `,`? */
1526- def isPostfixStar : Boolean =
1527- in.name == nme.raw.STAR && {
1528- val nxt = in.lookahead.token
1529- nxt == RPAREN || nxt == COMMA
1530- }
1531-
15321538 def infixTypeRest (t : Tree ): Tree =
1533- infixOps(t, canStartTypeTokens, refinedType, isType = true , isOperator = ! isPostfixStar)
1539+ infixOps(t, canStartTypeTokens, refinedType, isType = true ,
1540+ isOperator = ! followingIsVararg())
15341541
15351542 /** RefinedType ::= WithType {[nl] Refinement}
15361543 */
@@ -2046,7 +2053,7 @@ object Parsers {
20462053 case t =>
20472054 syntaxError(em " `inline` must be followed by an `if` or a `match` " , start)
20482055 t
2049- else expr1Rest(postfixExpr(), location)
2056+ else expr1Rest(postfixExpr(location ), location)
20502057 end expr1
20512058
20522059 def expr1Rest (t : Tree , location : Location ): Tree = in.token match
@@ -2068,22 +2075,25 @@ object Parsers {
20682075
20692076 def ascription (t : Tree , location : Location ): Tree = atSpan(startOffset(t)) {
20702077 in.token match {
2071- case USCORE =>
2078+ case USCORE if in.lookahead.isIdent(nme.raw. STAR ) =>
20722079 val uscoreStart = in.skipToken()
2073- if isIdent(nme.raw.STAR ) then
2074- in.nextToken()
2075- if ! (location.inArgs && in.token == RPAREN ) then
2076- if opStack.nonEmpty then
2077- report.errorOrMigrationWarning(
2078- em """ `_*` can be used only for last argument of method application.
2079- |It is no longer allowed in operands of infix operations. """ ,
2080- in.sourcePos(uscoreStart))
2081- else
2082- syntaxError(SeqWildcardPatternPos (), uscoreStart)
2083- Typed (t, atSpan(uscoreStart) { Ident (tpnme.WILDCARD_STAR ) })
2080+ val isVarargSplice = location.inArgs && followingIsVararg()
2081+ in.nextToken()
2082+ if isVarargSplice then
2083+ if sourceVersion.isAtLeast(`3.1`) then
2084+ report.errorOrMigrationWarning(
2085+ em " The syntax `x: _*` is no longer supported for vararg splices; use `x*` instead ${rewriteNotice(" 3.1" )}" ,
2086+ in.sourcePos(uscoreStart))
2087+ if sourceVersion == `3.1-migration` then
2088+ patch(source, Span (t.span.end, in.lastOffset), " *" )
2089+ else if opStack.nonEmpty then
2090+ report.errorOrMigrationWarning(
2091+ em """ `_*` can be used only for last argument of method application.
2092+ |It is no longer allowed in operands of infix operations. """ ,
2093+ in.sourcePos(uscoreStart))
20842094 else
2085- syntaxErrorOrIncomplete( IncorrectRepeatedParameterSyntax () )
2086- t
2095+ syntaxError( SeqWildcardPatternPos (), uscoreStart )
2096+ Typed (t, atSpan(uscoreStart) { Ident (tpnme. WILDCARD_STAR ) })
20872097 case AT if ! location.inPattern =>
20882098 annotations().foldLeft(t)(Annotated )
20892099 case _ =>
@@ -2152,7 +2162,7 @@ object Parsers {
21522162 // Don't error in non-strict mode, as the alternative syntax "implicit (x: T) => ... "
21532163 // is not supported by Scala2.x
21542164 report.errorOrMigrationWarning(
2155- s " This syntax is no longer supported; parameter needs to be enclosed in (...) ${rewriteNotice()}" ,
2165+ s " This syntax is no longer supported; parameter needs to be enclosed in (...) ${rewriteNotice(" 3.1 " )}" ,
21562166 source.atSpan(Span (start, in.lastOffset)))
21572167 in.nextToken()
21582168 val t = infixType()
@@ -2200,10 +2210,18 @@ object Parsers {
22002210 * | InfixExpr id [nl] InfixExpr
22012211 * | InfixExpr MatchClause
22022212 */
2203- def postfixExpr (): Tree = postfixExprRest(prefixExpr())
2213+ def postfixExpr (location : Location = Location .ElseWhere ): Tree =
2214+ val t = postfixExprRest(prefixExpr(), location)
2215+ if location.inArgs && followingIsVararg() then
2216+ Typed (t, atSpan(in.skipToken()) { Ident (tpnme.WILDCARD_STAR ) })
2217+ else
2218+ t
22042219
2205- def postfixExprRest (t : Tree ): Tree =
2206- infixOps(t, in.canStartExprTokens, prefixExpr, maybePostfix = true )
2220+ def postfixExprRest (t : Tree , location : Location = Location .ElseWhere ): Tree =
2221+ infixOps(t, in.canStartExprTokens, prefixExpr,
2222+ isType = false ,
2223+ isOperator = ! (location.inArgs && followingIsVararg()),
2224+ maybePostfix = true )
22072225
22082226 /** PrefixExpr ::= [`-' | `+' | `~' | `!'] SimpleExpr
22092227 */
@@ -2331,7 +2349,7 @@ object Parsers {
23312349 if (in.token == RPAREN ) Nil else commaSeparated(exprInParens)
23322350
23332351 /** ParArgumentExprs ::= `(' [‘using’] [ExprsInParens] `)'
2334- * | `(' [ExprsInParens `,'] PostfixExpr `:' `_' ` *' ')'
2352+ * | `(' [ExprsInParens `,'] PostfixExpr `*' ')'
23352353 */
23362354 def parArgumentExprs (): (List [Tree ], Boolean ) = inParens {
23372355 if in.token == RPAREN then
@@ -2610,37 +2628,44 @@ object Parsers {
26102628 ascription(p, location)
26112629 else p
26122630
2613- /** Pattern2 ::= [id `as'] InfixPattern
2631+ /** Pattern3 ::= InfixPattern [‘*’]
2632+ */
2633+ def pattern3 (): Tree =
2634+ val p = infixPattern()
2635+ if followingIsVararg() then
2636+ atSpan(in.skipToken()) {
2637+ Typed (p, Ident (tpnme.WILDCARD_STAR ))
2638+ }
2639+ else p
2640+
2641+ /** Pattern2 ::= [id `@'] Pattern3
26142642 */
2615- val pattern2 : () => Tree = () => infixPattern () match {
2643+ val pattern2 : () => Tree = () => pattern3 () match
26162644 case p @ Ident (name) if in.token == AT =>
26172645 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) }
2646+ pattern3() match {
26222647 case pt @ Bind (nme.WILDCARD , pt1 : Typed ) if pt.mods.is(Given ) =>
26232648 atSpan(startOffset(p), 0 ) { Bind (name, pt1).withMods(pt.mods) }
2649+ case Typed (Ident (nme.WILDCARD ), pt @ Ident (tpnme.WILDCARD_STAR )) =>
2650+ atSpan(startOffset(p), 0 ) { Typed (p, pt) }
26242651 case pt =>
26252652 atSpan(startOffset(p), 0 ) { Bind (name, pt) }
26262653 }
2627- case p @ Ident (tpnme.WILDCARD_STAR ) =>
2628- warnMigration(p)
2629- atSpan(startOffset(p)) { Typed (Ident (nme.WILDCARD ), p) }
26302654 case p =>
26312655 p
2632- }
26332656
2634- private def warnMigration (p : Tree ) =
2657+ private def warnStarMigration (p : Tree ) =
26352658 if sourceVersion.isAtLeast(`3.1`) then
26362659 report.errorOrMigrationWarning(
2637- " The syntax `x @ _*` is no longer supported; use `x : _ *` instead" ,
2660+ em " The syntax `x: _*` is no longer supported for vararg splices ; use `x*` instead " ,
26382661 in.sourcePos(startOffset(p)))
26392662
26402663 /** InfixPattern ::= SimplePattern {id [nl] SimplePattern}
26412664 */
26422665 def infixPattern (): Tree =
2643- infixOps(simplePattern(), in.canStartExprTokens, simplePattern, isOperator = in.name != nme.raw.BAR )
2666+ infixOps(simplePattern(), in.canStartExprTokens, simplePattern,
2667+ isType = false ,
2668+ isOperator = in.name != nme.raw.BAR && ! followingIsVararg())
26442669
26452670 /** SimplePattern ::= PatVar
26462671 * | Literal
@@ -2659,16 +2684,7 @@ object Parsers {
26592684 case id @ Ident (nme.raw.MINUS ) if isNumericLit => literal(startOffset(id))
26602685 case t => simplePatternRest(t)
26612686 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
2687+ wildcardIdent()
26722688 case LPAREN =>
26732689 atSpan(in.offset) { makeTupleOrParens(inParens(patternsOpt())) }
26742690 case QUOTE =>
@@ -2710,7 +2726,7 @@ object Parsers {
27102726 if (in.token == RPAREN ) Nil else patterns(location)
27112727
27122728 /** ArgumentPatterns ::= ‘(’ [Patterns] ‘)’
2713- * | ‘(’ [Patterns ‘,’] Pattern2 ‘:’ ‘_’ ‘ *’ ‘)’
2729+ * | ‘(’ [Patterns ‘,’] Pattern2 ‘*’ ‘)’
27142730 */
27152731 def argumentPatterns (): List [Tree ] =
27162732 inParens(patternsOpt(Location .InPatternArgs ))
0 commit comments