Skip to content

Commit

Permalink
Disallow xs: _* vararg syntax and use xs* instead
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolasstucki committed Nov 3, 2023
1 parent 8c602b3 commit 02615c9
Show file tree
Hide file tree
Showing 32 changed files with 93 additions and 88 deletions.
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

0 comments on commit 02615c9

Please sign in to comment.