Skip to content

Commit d691163

Browse files
authored
Merge pull request #3869 from abeln/wrapped-array
Fix #3675: don't unnecessarily wrap arrays when eliminating java varargs
2 parents e3e60b0 + 5482916 commit d691163

File tree

3 files changed

+34
-0
lines changed

3 files changed

+34
-0
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import scala.collection.{ mutable, immutable }
99
import PartialFunction._
1010
import collection.mutable
1111
import util.common.alwaysZero
12+
import dotty.tools.dotc.transform.TreeGen
1213

1314
object Definitions {
1415

@@ -338,6 +339,11 @@ class Definitions {
338339
def Predef_classOf(implicit ctx: Context) = Predef_classOfR.symbol
339340
lazy val Predef_undefinedR = ScalaPredefModule.requiredMethodRef("???")
340341
def Predef_undefined(implicit ctx: Context) = Predef_undefinedR.symbol
342+
// The set of all wrap{X, Ref}Array methods, where X is a value type
343+
val Predef_wrapArray = new PerRun[collection.Set[Symbol]]({ implicit ctx =>
344+
val methodNames = ScalaValueTypes.map(TreeGen.wrapArrayMethodName) + nme.wrapRefArray
345+
methodNames.map(ScalaPredefModule.requiredMethodRef(_).symbol)
346+
})
341347

342348
lazy val ScalaRuntimeModuleRef = ctx.requiredModuleRef("scala.runtime.ScalaRunTime")
343349
def ScalaRuntimeModule(implicit ctx: Context) = ScalaRuntimeModuleRef.symbol

compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
9494
private def seqToArray(tree: Tree, pt: Type)(implicit ctx: Context): Tree = tree match {
9595
case SeqLiteral(elems, elemtpt) =>
9696
JavaSeqLiteral(elems, elemtpt)
97+
case app@Apply(fun, args) if defn.Predef_wrapArray().contains(fun.symbol) => // rewrite a call to `wrapXArray(arr)` to `arr`
98+
args.head
9799
case _ =>
98100
val elemType = tree.tpe.elemType
99101
var elemClass = elemType.classSymbol

compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,4 +187,30 @@ class TestBCode extends DottyBytecodeTest {
187187
diffInstructions(instructions1, instructions2))
188188
}
189189
}
190+
191+
/** Verifies that arrays are not unnecessarily wrapped when passed to Java varargs methods */
192+
@Test def dontWrapArraysInJavaVarargs = {
193+
val source =
194+
"""
195+
|import java.nio.file._
196+
|class Test {
197+
| def test(xs: Array[String]) = {
198+
| val p4 = Paths.get("Hello", xs: _*)
199+
| }
200+
|}
201+
""".stripMargin
202+
203+
checkBCode(source) { dir =>
204+
val moduleIn = dir.lookupName("Test.class", directory = false)
205+
val moduleNode = loadClassNode(moduleIn.input)
206+
val method = getMethod(moduleNode, "test")
207+
208+
val arrayWrapped = instructionsFromMethod(method).exists {
209+
case inv: Invoke => inv.name.contains("wrapRefArray")
210+
case _ => false
211+
}
212+
213+
assert(!arrayWrapped, "Arrays should not be wrapped when passed to a Java varargs method\n")
214+
}
215+
}
190216
}

0 commit comments

Comments
 (0)