summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/transform/CleanUp.scala13
-rw-r--r--src/reflect/scala/reflect/internal/TreeInfo.scala14
-rw-r--r--test/files/instrumented/t6611.check1
-rw-r--r--test/files/instrumented/t6611.scala13
-rw-r--r--test/files/run/t6611.scala6
5 files changed, 42 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
index 1f353bb31c..bdcebf47b8 100644
--- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala
+++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
@@ -15,6 +15,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
import global._
import definitions._
import CODE._
+ import treeInfo.StripCast
/** the following two members override abstract members in Transform */
val phaseName: String = "cleanup"
@@ -618,14 +619,16 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
}
transformApply
- // This transform replaces Array(Predef.wrapArray(Array(...)), <tag>)
- // with just Array(...)
- case Apply(appMeth, List(Apply(wrapRefArrayMeth, List(array)), _))
+ // Replaces `Array(Predef.wrapArray(ArrayValue(...).$asInstanceOf[...]), <tag>)`
+ // with just `ArrayValue(...).$asInstanceOf[...]`
+ //
+ // See SI-6611; we must *only* do this for literal vararg arrays.
+ case Apply(appMeth, List(Apply(wrapRefArrayMeth, List(arg @ StripCast(ArrayValue(_, _)))), _))
if (wrapRefArrayMeth.symbol == Predef_wrapRefArray &&
appMeth.symbol == ArrayModule_overloadedApply.suchThat {
- _.tpe.resultType.dealias.typeSymbol == ObjectClass
+ _.tpe.resultType.dealias.typeSymbol == ObjectClass // [T: ClassTag](xs: T*): Array[T] post erasure
}) =>
- super.transform(array)
+ super.transform(arg)
case _ =>
super.transform(tree)
diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala
index 66326c90e9..bee92b446b 100644
--- a/src/reflect/scala/reflect/internal/TreeInfo.scala
+++ b/src/reflect/scala/reflect/internal/TreeInfo.scala
@@ -265,6 +265,20 @@ abstract class TreeInfo {
tree
}
+ /** Strips layers of `.asInstanceOf[T]` / `_.$asInstanceOf[T]()` from an expression */
+ def stripCast(tree: Tree): Tree = tree match {
+ case TypeApply(sel @ Select(inner, _), _) if isCastSymbol(sel.symbol) =>
+ stripCast(inner)
+ case Apply(TypeApply(sel @ Select(inner, _), _), Nil) if isCastSymbol(sel.symbol) =>
+ stripCast(inner)
+ case t =>
+ t
+ }
+
+ object StripCast {
+ def unapply(tree: Tree): Some[Tree] = Some(stripCast(tree))
+ }
+
/** Is tree a self or super constructor call? */
def isSelfOrSuperConstrCall(tree: Tree) = {
// stripNamedApply for SI-3584: adaptToImplicitMethod in Typers creates a special context
diff --git a/test/files/instrumented/t6611.check b/test/files/instrumented/t6611.check
new file mode 100644
index 0000000000..5cd691e93a
--- /dev/null
+++ b/test/files/instrumented/t6611.check
@@ -0,0 +1 @@
+Method call statistics:
diff --git a/test/files/instrumented/t6611.scala b/test/files/instrumented/t6611.scala
new file mode 100644
index 0000000000..821d5f3fbf
--- /dev/null
+++ b/test/files/instrumented/t6611.scala
@@ -0,0 +1,13 @@
+import scala.tools.partest.instrumented.Instrumentation._
+
+object Test {
+ def main(args: Array[String]) {
+ startProfiling()
+
+ // tests optimization in Cleanup for varargs reference arrays
+ val a = Array("")
+
+ stopProfiling()
+ printStatistics()
+ }
+}
diff --git a/test/files/run/t6611.scala b/test/files/run/t6611.scala
new file mode 100644
index 0000000000..c0297372f0
--- /dev/null
+++ b/test/files/run/t6611.scala
@@ -0,0 +1,6 @@
+object Test extends App {
+ val a = Array("1")
+ val a2 = Array(a: _*)
+ a2(0) = "2"
+ assert(a(0) == "1")
+}