diff --git a/community-build/community-projects/stdLib213 b/community-build/community-projects/stdLib213 index a6dcbd046597..00c8764bf289 160000 --- a/community-build/community-projects/stdLib213 +++ b/community-build/community-projects/stdLib213 @@ -1 +1 @@ -Subproject commit a6dcbd0465974543bb4dbe960300686a71383631 +Subproject commit 00c8764bf289396c0c6f8496c907f9a37f0415cb diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index c6d6d623924f..6a54b75936a6 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -445,6 +445,14 @@ object Parsers { finally staged = saved } + private var inArguments = false + private def withinArguments[T](in: Boolean)(body: => T): T = { + val saved = inArguments + inArguments = in + try body + finally inArguments = saved + } + /* ---------- TREE CONSTRUCTION ------------------------------------------- */ /** Convert tree to formal parameter list @@ -2009,7 +2017,14 @@ object Parsers { val uscoreStart = in.skipToken() if (isIdent(nme.raw.STAR)) { in.nextToken() - if (in.token != RPAREN) syntaxError(SeqWildcardPatternPos(), uscoreStart) + if in.token != RPAREN || !inArguments && sourceVersion.isAtLeast(`3.1`) then + syntaxError(SeqWildcardPatternPos(), uscoreStart) + else if !inArguments then + ctx.errorOrMigrationWarning( + "`_*` may only be used for last argument. Possibly using it inside non-method call parenthesis?", + in.sourcePos(uscoreStart) + ) + Typed(t, atSpan(uscoreStart) { Ident(tpnme.WILDCARD_STAR) }) } else { @@ -2185,7 +2200,9 @@ object Parsers { placeholderParams = param :: placeholderParams atSpan(start) { Ident(pname) } case LPAREN => - atSpan(in.offset) { makeTupleOrParens(inParens(exprsInParensOpt())) } + withinArguments(in = false) { + atSpan(in.offset) { makeTupleOrParens(inParens(exprsInParensOpt())) } + } case LBRACE | INDENT => canApply = false blockExpr() @@ -2274,14 +2291,16 @@ object Parsers { /** ParArgumentExprs ::= `(' [‘using’] [ExprsInParens] `)' * | `(' [ExprsInParens `,'] PostfixExpr `:' `_' `*' ')' */ - def parArgumentExprs(): (List[Tree], Boolean) = inParens { - if in.token == RPAREN then - (Nil, false) - else if isIdent(nme.using) then - in.nextToken() - (commaSeparated(argumentExpr), true) - else - (commaSeparated(argumentExpr), false) + def parArgumentExprs(): (List[Tree], Boolean) = withinArguments(in = true) { + inParens { + if in.token == RPAREN then + (Nil, false) + else if isIdent(nme.using) then + in.nextToken() + (commaSeparated(argumentExpr), true) + else + (commaSeparated(argumentExpr), false) + } } /** ArgumentExprs ::= ParArgumentExprs @@ -2632,12 +2651,16 @@ object Parsers { // `x: _*' is parsed in `ascription' if (isIdent(nme.raw.STAR)) { in.nextToken() - if (in.token != RPAREN) syntaxError(SeqWildcardPatternPos(), wildIdent.span) + if (in.token != RPAREN || !inArguments) syntaxError(SeqWildcardPatternPos(), wildIdent.span) atSpan(wildIdent.span) { Ident(tpnme.WILDCARD_STAR) } } else wildIdent case LPAREN => - atSpan(in.offset) { makeTupleOrParens(inParens(patternsOpt())) } + atSpan(in.offset) { + withinArguments(in = false) { + makeTupleOrParens(inParens(patternsOpt())) + } + } case QUOTE => simpleExpr() case XMLSTART => @@ -2671,7 +2694,7 @@ object Parsers { * | ‘(’ [Patterns ‘,’] Pattern2 ‘:’ ‘_’ ‘*’ ‘)’ */ def argumentPatterns(): List[Tree] = - inParens(patternsOpt()) + withinArguments(in = true) { inParens(patternsOpt()) } /* -------- MODIFIERS and ANNOTATIONS ------------------------------------------- */ diff --git a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala index 2417294c50ed..995033b4c475 100644 --- a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala +++ b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala @@ -627,7 +627,7 @@ trait ParallelTesting extends RunnerOrchestration { self => lazy val actualErrors = reporters.foldLeft(0)(_ + _.errorCount) def hasMissingAnnotations = getMissingExpectedErrors(errorMap, reporters.iterator.flatMap(_.errors)) def showErrors = "-> following the errors:\n" + - reporters.flatMap(_.allErrors.map(e => e.pos.toString + ": " + e.message)).mkString(start = "at ", sep = "\n at ", end = "") + reporters.flatMap(_.allErrors.map(e => e.pos.line.toString + ": " + e.message)).mkString(start = "at ", sep = "\n at ", end = "") if (compilerCrashed) Some(s"Compiler crashed when compiling: ${testSource.title}") else if (actualErrors == 0) Some(s"\nNo errors found when compiling neg test $testSource") diff --git a/tests/neg/i7972.scala b/tests/neg/i7972.scala index 1003e30f460e..abe3185d6b03 100644 --- a/tests/neg/i7972.scala +++ b/tests/neg/i7972.scala @@ -1,18 +1,18 @@ object O { - def m1(a: Int*) = (a: _*) // error: Cannot return repeated parameter type Int* + def m1(a: Int*) = (a: _*) // error // error: Cannot return repeated parameter type Int* def m2(a: Int*) = { // error: Cannot return repeated parameter type Int* - val b = (a: _*) // error: Cannot return repeated parameter type Int* + val b = (a: _*) // error // error: Cannot return repeated parameter type Int* b } def m3(a: Int*): Any = { - val b = (a: _*) // error: Cannot return repeated parameter type Int* + val b = (a: _*) // error // error: Cannot return repeated parameter type Int* b } - def m4(a: 2*) = (a: _*) // error: Cannot return repeated parameter type Int* + def m4(a: 2*) = (a: _*) // error // error: Cannot return repeated parameter type Int* } class O(a: Int*) { - val m = (a: _*) // error: Cannot return repeated parameter type Int* + val m = (a: _*) // error // error: Cannot return repeated parameter type Int* } diff --git a/tests/neg/i8715.scala b/tests/neg/i8715.scala new file mode 100644 index 000000000000..aedb32cffdcb --- /dev/null +++ b/tests/neg/i8715.scala @@ -0,0 +1,2 @@ +@main +def Test = List(42) match { case List(xs @ (ys: _*)) => xs } // error diff --git a/tests/neg/t5702-neg-bad-and-wild.scala b/tests/neg/t5702-neg-bad-and-wild.scala new file mode 100644 index 000000000000..1fc423d843f9 --- /dev/null +++ b/tests/neg/t5702-neg-bad-and-wild.scala @@ -0,0 +1,29 @@ + +object Test { + case class K(i: Int) + + def main(args: Array[String]) = { + val k = new K(9) + val is = List(1,2,3) + + is match { + case List(1, _*,) => // error // error // error: bad use of _* (a sequence pattern must be the last pattern) + // illegal start of simple pattern + case List(1, _*3,) => // error // error: illegal start of simple pattern + //case List(1, _*3:) => // poor recovery by parens + case List(1, x*) => // error: use _* to match a sequence + case List(x*, 1) => // error: trailing * is not a valid pattern + case (1, x*) => // error: trailing * is not a valid pattern + case (1, x@_*) => // error: bad use of _* (sequence pattern not allowed) + } + +// good syntax, bad semantics, detected by typer +//gowild.scala:14: error: star patterns must correspond with varargs parameters + val K(x @ _*) = k + val K(ns @ _*, x) = k // error: bad use of _* (a sequence pattern must be the last pattern) + val (b, _ * ) = (5,6) // error: bad use of _* (sequence pattern not allowed) +// no longer complains +//bad-and-wild.scala:15: error: ')' expected but '}' found. + } +} + diff --git a/tests/pos-scala2/i8715b.scala b/tests/pos-scala2/i8715b.scala new file mode 100644 index 000000000000..18f053806496 --- /dev/null +++ b/tests/pos-scala2/i8715b.scala @@ -0,0 +1,4 @@ +// from stdlib +class Test { + def printf(text: String, args: Any*): Unit = { System.out.print(text format (args : _*)) } +} \ No newline at end of file diff --git a/tests/untried/neg/t5702-neg-bad-and-wild.scala b/tests/untried/neg/t5702-neg-bad-and-wild.scala deleted file mode 100644 index aadda37da7c3..000000000000 --- a/tests/untried/neg/t5702-neg-bad-and-wild.scala +++ /dev/null @@ -1,29 +0,0 @@ - -object Test { - case class K(i: Int) - - def main(args: Array[String]) { - val k = new K(9) - val is = List(1,2,3) - - is match { - case List(1, _*,) => // bad use of _* (a sequence pattern must be the last pattern) - // illegal start of simple pattern - case List(1, _*3,) => // illegal start of simple pattern - //case List(1, _*3:) => // poor recovery by parens - case List(1, x*) => // use _* to match a sequence - case List(x*, 1) => // trailing * is not a valid pattern - case (1, x*) => // trailing * is not a valid pattern - case (1, x@_*) => // bad use of _* (sequence pattern not allowed) - } - -// good syntax, bad semantics, detected by typer -//gowild.scala:14: error: star patterns must correspond with varargs parameters - val K(is @ _*) = k - val K(ns @ _*, x) = k // bad use of _* (a sequence pattern must be the last pattern) - val (b, _ * ) = (5,6) // bad use of _* (sequence pattern not allowed) -// no longer complains -//bad-and-wild.scala:15: error: ')' expected but '}' found. - } -} -