aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-12-21 12:38:16 +0100
committerMartin Odersky <odersky@gmail.com>2014-12-21 12:38:33 +0100
commitf98ce3f42a77802fc98eb0f12636efc1f25c2d1b (patch)
tree451c5d72a40acfa4ee5c75f8ebcf033964d3e887
parent3648ea82d5150d0685bbde3991abcfe007c38987 (diff)
downloaddotty-f98ce3f42a77802fc98eb0f12636efc1f25c2d1b.tar.gz
dotty-f98ce3f42a77802fc98eb0f12636efc1f25c2d1b.tar.bz2
dotty-f98ce3f42a77802fc98eb0f12636efc1f25c2d1b.zip
Fix passing : _* arguments to Java methods
Arguments of the form (xs: _*) which are passed to Java methods need to be converted to arrays, not sequences.
-rw-r--r--src/dotty/runtime/Arrays.scala11
-rw-r--r--src/dotty/tools/dotc/core/StdNames.scala1
-rw-r--r--src/dotty/tools/dotc/transform/ElimRepeated.scala32
-rw-r--r--tests/pending/pos/arrays2.scala23
-rw-r--r--tests/pos/arrays2.scala30
5 files changed, 69 insertions, 28 deletions
diff --git a/src/dotty/runtime/Arrays.scala b/src/dotty/runtime/Arrays.scala
index e7f819df8..5767991e5 100644
--- a/src/dotty/runtime/Arrays.scala
+++ b/src/dotty/runtime/Arrays.scala
@@ -2,7 +2,7 @@ package dotty.runtime
import scala.reflect.ClassTag
-/** All but the first operation should be short-circuited and implemented specially by
+/** All but the first two operations should be short-circuited and implemented specially by
* the backend.
*/
object Arrays {
@@ -12,7 +12,14 @@ object Arrays {
*/
def newGenericArray[T](length: Int)(implicit tag: ClassTag[T]): Array[T] =
tag.newArray(length)
-
+
+ /** Convert a sequence to a Java array with element type given by `clazz`. */
+ def seqToArray[T](xs: Seq[T], clazz: Class[_]): Array[T] = {
+ val arr = java.lang.reflect.Array.newInstance(clazz, xs.length).asInstanceOf[Array[T]]
+ xs.copyToArray(arr)
+ arr
+ }
+
/** Create an array of type T. T must be of form Array[E], with
* E being a reference type.
*/
diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala
index 04bcf616d..4e3fa27ec 100644
--- a/src/dotty/tools/dotc/core/StdNames.scala
+++ b/src/dotty/tools/dotc/core/StdNames.scala
@@ -468,6 +468,7 @@ object StdNames {
val selectTerm: N = "selectTerm"
val selectType: N = "selectType"
val self: N = "self"
+ val seqToArray: N = "seqToArray"
val setAccessible: N = "setAccessible"
val setAnnotations: N = "setAnnotations"
val setSymbol: N = "setSymbol"
diff --git a/src/dotty/tools/dotc/transform/ElimRepeated.scala b/src/dotty/tools/dotc/transform/ElimRepeated.scala
index ff56ae872..28131e1e9 100644
--- a/src/dotty/tools/dotc/transform/ElimRepeated.scala
+++ b/src/dotty/tools/dotc/transform/ElimRepeated.scala
@@ -3,12 +3,14 @@ package transform
import core._
import Names._
+import StdNames.nme
import Types._
import dotty.tools.dotc.transform.TreeTransforms.{AnnotationTransformer, TransformerInfo, MiniPhaseTransform, TreeTransformer}
-import ast.Trees.flatten
+import ast.Trees._
import Flags._
import Contexts.Context
import Symbols._
+import Constants._
import Denotations._, SymDenotations._
import Decorators.StringInterpolators
import dotty.tools.dotc.ast.tpd
@@ -56,9 +58,33 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer with Annotati
override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree =
transformTypeOfTree(tree)
- override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree =
- transformTypeOfTree(tree) // should also transform the tree if argument needs adaptation
+ override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = {
+ val args1 = tree.args.map {
+ case arg: Typed if isWildcardStarArg(arg) =>
+ if (tree.fun.symbol.is(JavaDefined) && arg.expr.tpe.derivesFrom(defn.SeqClass))
+ seqToArray(arg.expr)
+ else arg.expr
+ case arg => arg
+ }
+ transformTypeOfTree(cpy.Apply(tree)(tree.fun, args1))
+ }
+ /** Convert sequence argument to Java array */
+ private def seqToArray(tree: Tree)(implicit ctx: Context): Tree = tree match {
+ case SeqLiteral(elems) =>
+ JavaSeqLiteral(elems)
+ case _ =>
+ val elemType = tree.tpe.firstBaseArgInfo(defn.SeqClass)
+ var elemClass = elemType.classSymbol
+ if (defn.PhantomClasses contains elemClass) elemClass = defn.ObjectClass
+ ref(defn.DottyArraysModule)
+ .select(nme.seqToArray)
+ .appliedToType(elemType)
+ .appliedTo(tree, Literal(Constant(elemClass.typeRef)))
+ .ensureConforms(defn.ArrayType(elemType))
+ // Because of phantomclasses, the Java array's type might not conform to the resturn type
+ }
+
override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree =
transformTypeOfTree(tree)
diff --git a/tests/pending/pos/arrays2.scala b/tests/pending/pos/arrays2.scala
deleted file mode 100644
index 795c486e3..000000000
--- a/tests/pending/pos/arrays2.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-case class C();
-
-object arrays2 {
-
- def main(args: Array[String]): Unit = {
- val a: Array[Array[C]] = new Array[Array[C]](2);
- a(0) = new Array[C](2);
- a(0)(0) = new C();
- }
-}
-
-// #2422
-object arrays4 {
- val args = Array[String]("World")
- "Hello %1$s".format(args: _*)
-}
-
-// #2461
-object arrays3 {
- import scala.collection.JavaConversions._
- def apply[X](xs : X*) : java.util.List[X] = java.util.Arrays.asList(xs: _*)
-}
-
diff --git a/tests/pos/arrays2.scala b/tests/pos/arrays2.scala
new file mode 100644
index 000000000..c9e5e0bfc
--- /dev/null
+++ b/tests/pos/arrays2.scala
@@ -0,0 +1,30 @@
+case class C();
+
+object arrays2 {
+
+ def main(args: Array[String]): Unit = {
+ val a: Array[Array[C]] = new Array[Array[C]](2);
+ a(0) = new Array[C](2);
+ a(0)(0) = new C();
+ }
+}
+
+// #2422
+object arrays4 {
+ val args = Array[String]("World")
+ "Hello %1$s".format(args: _*)
+}
+
+// #2461
+object arrays3 {
+ import scala.collection.JavaConversions._
+ def apply[X](xs : X*) : java.util.List[X] = java.util.Arrays.asList(xs: _*)
+
+ def apply1[X <: String](xs : X*) : java.util.List[X] = java.util.Arrays.asList(xs: _*)
+ def apply2[X <: AnyVal](xs : X*) : java.util.List[X] = java.util.Arrays.asList(xs: _*)
+ def apply3(xs : Int*) : java.util.List[Int] = java.util.Arrays.asList(xs: _*)
+ def apply4(xs : Unit*) : java.util.List[Unit] = java.util.Arrays.asList(xs: _*)
+ def apply5(xs : Null*) : java.util.List[Null] = java.util.Arrays.asList(xs: _*)
+ def apply6(xs : Nothing*) : java.util.List[Nothing] = java.util.Arrays.asList(xs: _*)
+}
+