bug
bug copied to clipboard
An Array cannot be used in place of varargs with type parameters.
This happens when vararg type has type parameters.
Both Array and mutable.Seq are invariant. However using Array as an argument in vararg function fails, while mutable.Seq works.
object Main {
def main(args: Array[String]) {
bar(new B)
}
def bar(b: B) {
val array = Array(b, b)
val seq :scala.collection.mutable.Seq[B] = array
foo(b, b)
foo(seq: _*) //works
foo(array: _*) //compiler error
}
def foo(s: A[_]*) {
s.foreach(println)
}
}
class A[T]
class B extends A[String]
Compiler error:
error: type mismatch;
found : Array[B]
required: Array[A[?>: Nothing <: Any]]
foo(array: _*)
one error found
Everything works when vararg type does not have any type parameters:
object Main {
def main(args: Array[String]) {
bar(new B)
}
def bar(b: B) {
val array = Array(b, b)
val seq :scala.collection.mutable.Seq[B] = array
foo(b, b)
foo(seq: _*)
foo(array: _*)
}
def foo[T](s: A*) {
s.foreach(println)
}
}
class A
class B extends A
Tested on 2.8.1.final and 2.9.0.r23541.
Imported From: https://issues.scala-lang.org/browse/SI-4003?orig=1 Reporter: @lexn82
@adriaanm said: let's have a look at the code that does type check after uncurry (scalac -Xprint:uncurry):
The vararg is considered a scala.collection.Seq[A[]], Seq is covariant so that a mutable.Seq[B] <: collection.Seq[A[]]
def bar(b: B): Unit = {
val array: Array[B] = ...
val seq: mutable.Seq[B] = wrapRefArray[B](array);
foo(wrapRefArray[A[_]](Array[A[_]]{b, b}));
foo(seq)
};
def foo(s: Seq[A[_]]): Unit = ...
So, back to the bug: when passing array to foo, the compiler complains. I guess this is indeed a bug since val x : Seq[A[_]] = array compiles (uncurry turns it into val x: Seq[A[_]] = scala.this.Predef.wrapRefArray[B](array);)
Workaround:
val array : Array[A[_]] = Array(b, b)
In Scala 2.13.0, the former code is also a compilation error, and the latter code is also a compilation error.
(The package names were compiled as pattern1 and pattern2, respectively.)
The former compilation error
[error] /xxx/src/main/scala/Main1.scala:13:9: type mismatch;
[error] found : Seq[pattern1.B] (in scala.collection.mutable)
[error] required: Seq[pattern1.A[?]] (in scala.collection.immutable)
[error] foo(seq: _*) //works
[error] ^
[error] /xxx/src/main/scala/Main1.scala:14:9: type mismatch;
[error] found : Array[pattern1.B]
[error] required: Array[pattern1.A[?]]
[error] Note: pattern1.B <: pattern1.A[?], but class Array is invariant in type T.
[error] You may wish to investigate a wildcard type such as `_ <: pattern1.A[?]`. (SLS 3.2.10)
[error] foo(array: _*) //compiler error
[error] ^
The latter compilation error
[error] /xxx/src/main/scala/Main2.scala:13:9: type mismatch;
[error] found : Seq[pattern2.B] (in scala.collection.mutable)
[error] required: Seq[pattern2.A] (in scala.collection.immutable)
[error] foo(seq: _*)
[error] ^
the latter one is because varargs are scala.Seq, which is now an alias for scala.collection.immutable.Seq rather than scala.collection.Seq. If you change the code to val seq :scala.collection.immutable.Seq[B] = array it may work (I can't check right now)
surely! After rewriting the code, the compilation passed.