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

Disallow xs: _* vararg syntax and use xs* instead #18812

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2343,12 +2343,13 @@ object Parsers {
val isVarargSplice = location.inArgs && followingIsVararg()
in.nextToken()
if isVarargSplice then
report.errorOrMigrationWarning(
em"The syntax `x: _*` is no longer supported for vararg splices; use `x*` instead${rewriteNotice(`future-migration`)}",
in.sourcePos(uscoreStart),
future)
if sourceVersion == `future-migration` then
patch(source, Span(t.span.end, in.lastOffset), "*")
if !in.featureEnabled(Feature.ascriptionVarargsUnpacking) then
report.errorOrMigrationWarning(
em"The syntax `x: _*` is no longer supported for vararg splices; use `x*` instead${rewriteNotice(`3.4-migration`)}",
in.sourcePos(uscoreStart),
`3.4`)
if sourceVersion == `3.4-migration` then
patch(source, Span(t.span.end, in.lastOffset), "*")
else if opStack.nonEmpty then
report.errorOrMigrationWarning(
em"""`_*` can be used only for last argument of method application.
Expand Down
6 changes: 5 additions & 1 deletion project/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1008,7 +1008,10 @@ object Build {
Seq("-sourcepath", ((Compile/sourceManaged).value / "scala-library-src").toString)
},
Compile / doc / scalacOptions += "-Ydocument-synthetic-types",
scalacOptions += "-Ycompile-scala2-library",
scalacOptions ++= Seq(
"-Ycompile-scala2-library",
"-language:deprecated.ascriptionVarargsUnpacking",
),
scalacOptions -= "-Xfatal-warnings",
ivyConfigurations += SourceDeps.hide,
transitiveClassifiers := Seq("sources"),
Expand Down Expand Up @@ -1361,6 +1364,7 @@ object Build {
dependsOn(`scala3-library-bootstrappedJS`).
settings(
bspEnabled := false,
scalacOptions += "-language:deprecated.ascriptionVarargsUnpacking",
scalacOptions --= Seq("-Xfatal-warnings", "-deprecation"),

// Required to run Scala.js tests.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ object PatternMatching {

// http://dotty.epfl.ch/docs/reference/changed/vararg-patterns.html
def containsConsecutive(list: List[Int]): Boolean = list match {
case List(a, b, xs: _ *) => if (a == b) true else containsConsecutive(b :: xs.toList)
case List(a, _ : _*) => false
case List(a, b, xs*) => if (a == b) true else containsConsecutive(b :: xs.toList)
case List(a, _*) => false
case Nil => false
}

Expand All @@ -86,7 +86,7 @@ object PatternMatching {
import seqPattern._

def greet(fullName: String) = fullName match {
case Names(lastName, firstName, _: _*) => "Good morning, " + firstName + " " + lastName + "!"
case Names(lastName, firstName, _*) => "Good morning, " + firstName + " " + lastName + "!"
case _ => "Welcome! Please make sure to fill in your name!"
}

Expand Down
36 changes: 18 additions & 18 deletions tests/explicit-nulls/neg/varargs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,34 @@ class Varargs {
f1(null) // error
f1("")
f1("", null) // error
f1(null: _*) // error
f1(null*) // error

f1(xs1: _*)
f1(xs2: _*) // error
f1(xs3: _*) // error
f1(xs4: _*) // error
f1(xs1*)
f1(xs2*) // error
f1(xs3*) // error
f1(xs4*) // error

f1(ys1: _*)
f1(ys2: _*) // error
f1(ys3: _*) // error
f1(ys4: _*) // error
f1(ys1*)
f1(ys2*) // error
f1(ys3*) // error
f1(ys4*) // error
}

def test2 = {
f2()
f2(null)
f2("")
f2("", null)
f2(null: _*) // error
f2(null*) // error

f2(xs1: _*)
f2(xs2: _*)
f2(xs3: _*) // error
f2(xs4: _*) // error
f2(xs1*)
f2(xs2*)
f2(xs3*) // error
f2(xs4*) // error

f2(ys1: _*)
f2(ys2: _*)
f2(ys3: _*) // error
f2(ys4: _*) // error
f2(ys1*)
f2(ys2*)
f2(ys3*) // error
f2(ys4*) // error
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ class S {
val arg3: Array[String] | Null = ???
val arg4: Array[String | Null] | Null = ???

j.foo(arg1: _*)
j.foo(arg2: _*)
j.foo(arg3: _*) // error
j.foo(arg4: _*) // error
j.foo(arg1*)
j.foo(arg2*)
j.foo(arg3*) // error
j.foo(arg4*) // error
}
18 changes: 9 additions & 9 deletions tests/explicit-nulls/unsafe-common/unsafe-java-varargs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ def test2 = {
val ys3: Array[String | Null] | Null = ???
val ys4: Array[String] | Null = ???

Paths.get("", xs1: _*)
Paths.get("", xs2: _*)
Paths.get("", xs3: _*) // error
Paths.get("", xs4: _*) // error
Paths.get("", xs1*)
Paths.get("", xs2*)
Paths.get("", xs3*) // error
Paths.get("", xs4*) // error

Paths.get("", ys1: _*)
Paths.get("", ys2: _*)
Paths.get("", ys3: _*) // error
Paths.get("", ys4: _*) // error
Paths.get("", ys1*)
Paths.get("", ys2*)
Paths.get("", ys3*) // error
Paths.get("", ys4*) // error

Paths.get("", null: _*) // error
Paths.get("", null*) // error
}
2 changes: 1 addition & 1 deletion tests/neg/i6622d.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import scala.compiletime.*
object Test {

def main(args: Array[String]): Unit = {
println(StringContext("abc").code(Seq.empty[Any]:_*)) // error
println(StringContext("abc").code(Seq.empty[Any]*)) // error
}

}
2 changes: 1 addition & 1 deletion tests/neg/i6622e.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import scala.compiletime.*
object Test {

def main(args: Array[String]): Unit = {
println(StringContext(Seq.empty[String]:_*).code(Seq.empty[Any]:_*)) // error
println(StringContext(Seq.empty[String]*).code(Seq.empty[Any]*)) // error
}

}
4 changes: 2 additions & 2 deletions tests/patmat/exhaustive_heuristics.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ object Test {
// well, in truth, we do rewrite List() to Nil, but otherwise we do nothing
// the full rewrite List(a, b) to a :: b :: Nil, for example is planned (but not sure it's a good idea)
List(true, false) match {
case List(_, _, _:_*) =>
case List(node, _:_*) =>
case List(_, _, _*) =>
case List(node, _*) =>
case Nil =>
}

Expand Down
2 changes: 1 addition & 1 deletion tests/pos-deep-subtype/i7580.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

def foo =
val List(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, _:_*) = List.fill(25)(0)
val List(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, _*) = List.fill(25)(0)

()
6 changes: 3 additions & 3 deletions tests/pos-special/stdlib/collection/StringOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -862,7 +862,7 @@ final class StringOps(private val s: String) extends AnyVal {
* @param groupNames The names of the groups in the pattern, in the order they appear.
*/
@deprecated("use inline group names like (?<year>X) instead", "2.13.7")
def r(groupNames: String*): Regex = new Regex(s, groupNames: _*)
def r(groupNames: String*): Regex = new Regex(s, groupNames*)

/**
* @throws java.lang.IllegalArgumentException If the string does not contain a parsable `Boolean`.
Expand Down Expand Up @@ -987,7 +987,7 @@ final class StringOps(private val s: String) extends AnyVal {
* @throws java.lang.IllegalArgumentException
*/
def format(args : Any*): String =
java.lang.String.format(s, args map unwrapArg: _*)
java.lang.String.format(s, args map unwrapArg*)

/** Like `format(args*)` but takes an initial `Locale` parameter
* which influences formatting as in `java.lang.String`'s format.
Expand All @@ -1003,7 +1003,7 @@ final class StringOps(private val s: String) extends AnyVal {
* @throws java.lang.IllegalArgumentException
*/
def formatLocal(l: java.util.Locale, args: Any*): String =
java.lang.String.format(l, s, args map unwrapArg: _*)
java.lang.String.format(l, s, args map unwrapArg*)

def compare(that: String): Int = s.compareTo(that)

Expand Down
2 changes: 1 addition & 1 deletion tests/pos-special/stdlib/collection/View.scala
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ object View extends IterableFactory[View] {

def newBuilder[A]: Builder[A, View[A]] = ArrayBuffer.newBuilder[A].mapResult(from)

override def apply[A](xs: A*): View[A] = new Elems(xs: _*)
override def apply[A](xs: A*): View[A] = new Elems(xs*)

/** The empty view */
@SerialVersionUID(3L)
Expand Down
2 changes: 1 addition & 1 deletion tests/pos/i13349.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ object Stream {
def empty[A]: Stream[A] = Empty

def apply[A](as: A*): Stream[A] =
if (as.isEmpty) empty else cons(as.head, apply(as.tail: _*))
if (as.isEmpty) empty else cons(as.head, apply(as.tail*))

}
2 changes: 1 addition & 1 deletion tests/pos/i16105.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ trait QuerySQLSyntaxProvider[S <: SQLSyntaxSupport[A], A]{
}

def include(syntaxProviders: QuerySQLSyntaxProvider[_, _]*) = {
syntax(syntaxProviders.map(_.resultName): _*)
syntax(syntaxProviders.map(_.resultName)*)
}

def syntax(resultNames: ResultNameSQLSyntaxProvider[_, _]*) = ???
4 changes: 2 additions & 2 deletions tests/pos/i16562.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ class Test:
val a: Array[Any] = Array[Any]()
val b: Array[Any] = Array[Any]()

def ko(p: Boolean): Unit = foo((if p then a else b): _*)
def ok(p: Boolean): Unit = foo({ val x = if p then a else b; x }: _*)
def ko(p: Boolean): Unit = foo((if p then a else b)*)
def ok(p: Boolean): Unit = foo({ val x = if p then a else b; x }*)

def foo(in: Any*): Unit = ()
4 changes: 2 additions & 2 deletions tests/pos/i4984.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ class Test {
}

def test2(xs: Array[Int]): Seq[Int] = xs match {
case Array2(x, y, xs:_*) => xs
case Array2(x, y, xs*) => xs
}

def test3(xs: Array[Int]): Seq[Int] = xs match {
case Array2(xs:_*) => xs
case Array2(xs*) => xs
}
}
6 changes: 3 additions & 3 deletions tests/pos/i5039.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
class I0 {
List(null:_*)
List[Null](null:_*)
List[Nothing](null:_*)
List(null*)
List[Null](null*)
List[Nothing](null*)
}
2 changes: 1 addition & 1 deletion tests/pos/i9050.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ object Foo {
val foo = scala.collection.mutable.ArrayBuffer.empty[Seq[Double]]
val bar = Seq.empty[Double]
foo.append(bar)
foo.append(Seq(bar):_*)
foo.append(Seq(bar)*)
}
2 changes: 1 addition & 1 deletion tests/pos/t0305.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ object Test extends App {
def foo(is:Int*) = 1;
def foo(i:Int) = 2;

assert(foo( List(3):_* ) == 1)
assert(foo( List(3)* ) == 1)
}
2 changes: 1 addition & 1 deletion tests/run-macros/f-interpolator-tests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ object StringContextTestUtils:
// Use this String interpolator to avoid problems with a locale-dependent decimal mark.
def locally(numbers: String*): String =
val numbersWithCorrectLocale = numbers.map(applyProperLocale)
sc.s(numbersWithCorrectLocale: _*)
sc.s(numbersWithCorrectLocale*)

// Handles cases like locally"3.14" - it's prettier than locally"${"3.14"}".
def locally(): String = sc.parts.map(applyProperLocale).mkString
2 changes: 1 addition & 1 deletion tests/run-macros/refined-selectable-macro/Macro_2.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ object Macro2 {
inline def apply[R <: Record](elems: (String, Any)*) : R = ${ applyImpl[R]('elems) }

def applyImpl[R <: Record: Type](elems: Expr[Seq[(String, Any)]])(using Quotes) = {
'{ new Record($elems:_*).asInstanceOf[R] }
'{ new Record($elems*).asInstanceOf[R] }
}

def fromUntypedTuple(elems: (String, Any)*): Record = new Record(elems*)
Expand Down
4 changes: 2 additions & 2 deletions tests/run/i4984b.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ object Test {
}

def test2(xs: Array[Int]): Seq[Int] = xs match {
case Array2(x, y, xs:_*) => xs
case Array2(x, y, xs*) => xs
}

def test3(xs: Array[Int]): Seq[Int] = xs match {
case Array2(xs:_*) => xs
case Array2(xs*) => xs
}

def main(args: Array[String]): Unit = {
Expand Down
4 changes: 2 additions & 2 deletions tests/run/i4984c.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ object Test {
}

def test2(xs: Array[Int]): Seq[Int] = xs match {
case Array2(x, y, xs:_*) => xs
case Array2(x, y, xs*) => xs
}

def test3(xs: Array[Int]): Seq[Int] = xs match {
case Array2(xs:_*) => xs
case Array2(xs*) => xs
}

def main(args: Array[String]): Unit = {
Expand Down
4 changes: 2 additions & 2 deletions tests/run/i4984d.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ object Test {
}

def test2(xs: Array[Int]): Seq[Int] = xs match {
case Array2(x, y, xs:_*) => xs
case Array2(x, y, xs*) => xs
}

def test3(xs: Array[Int]): Seq[Int] = xs match {
case Array2(xs:_*) => xs
case Array2(xs*) => xs
}

def main(args: Array[String]): Unit = {
Expand Down
4 changes: 2 additions & 2 deletions tests/run/i4984e.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ object Test {
}

def test2(xs: Array[Int]): Seq[Int] = xs match {
case Array2(x, y, xs:_*) => xs
case Array2(x, y, xs*) => xs
}

def test3(xs: Array[Int]): Seq[Int] = xs match {
case Array2(xs:_*) => xs
case Array2(xs*) => xs
}

def main(args: Array[String]): Unit = {
Expand Down
8 changes: 4 additions & 4 deletions tests/run/i8977.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ object Test {

def main(args: Array[String]): Unit = {
System.out.printf("pi = %6.4f\n", pi)
System.out.printf("pi = %6.4f\n", Seq[scala.Double](pi):_*)
System.out.printf("pi = %6.4f\n", Seq[java.lang.Double](pi):_*)
System.out.printf("pi = %6.4f\n", Array[scala.Double](pi):_*)
System.out.printf("pi = %6.4f\n", Array[java.lang.Double](pi):_*)
System.out.printf("pi = %6.4f\n", Seq[scala.Double](pi)*)
System.out.printf("pi = %6.4f\n", Seq[java.lang.Double](pi)*)
System.out.printf("pi = %6.4f\n", Array[scala.Double](pi)*)
System.out.printf("pi = %6.4f\n", Array[java.lang.Double](pi)*)
}
}
10 changes: 5 additions & 5 deletions tests/run/iterator-from.scala
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ object Test extends App {
0 until maxLength foreach {length =>
val keyValues = (0 until length map {_ => (R nextInt maxKey, R nextInt maxValue)}).toList
val keys = keyValues map (_._2)
testSet(immutable.BitSet(keys:_*), keys)
testSet(immutable.TreeSet(keys:_*), keys)
testSet(mutable.TreeSet(keys:_*), keys)
testSet(immutable.BitSet(keys*), keys)
testSet(immutable.TreeSet(keys*), keys)
testSet(mutable.TreeSet(keys*), keys)
val days = keys map {n => Weekday(n % Weekday.values.size)}
testSet(Weekday.ValueSet(days:_*), days)
testSet(Weekday.ValueSet(days*), days)

val treeMap = immutable.TreeMap(keyValues:_*)
val treeMap = immutable.TreeMap(keyValues*)
testMap(treeMap, keyValues)
testMap(treeMap.view.filterKeys(_ % 2 == 0).to(SortedMap), keyValues filter (_._1 % 2 == 0))
testMap(treeMap.view.mapValues(_ + 1).to(SortedMap), keyValues map {case (k,v) => (k, v + 1)})
Expand Down
Loading
Loading