diff options
-rw-r--r-- | src/dotty/runtime/Arrays.scala | 11 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/StdNames.scala | 1 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/ElimRepeated.scala | 32 | ||||
-rw-r--r-- | tests/pending/pos/arrays2.scala | 23 | ||||
-rw-r--r-- | tests/pos/arrays2.scala | 30 |
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: _*) +} + |