summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2012-11-03 13:34:20 +0100
committerJason Zaugg <jzaugg@gmail.com>2012-11-03 23:25:13 +0100
commitdad886659faca4fba2d4937c9bc6780591b02c27 (patch)
tree0fcb5ab4e20c6570bd15cf773c9ec9d1d74f7e81 /src
parentb5e3eafabe4b9cfe1e6de9eeedfe1140afeaa4eb (diff)
downloadscala-dad886659faca4fba2d4937c9bc6780591b02c27.tar.gz
scala-dad886659faca4fba2d4937c9bc6780591b02c27.tar.bz2
scala-dad886659faca4fba2d4937c9bc6780591b02c27.zip
SI-6611 Tighten up an unsafe array optimization
The net was cast too wide and was unsafely optimizing away array copies.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/transform/CleanUp.scala13
-rw-r--r--src/reflect/scala/reflect/internal/TreeInfo.scala14
2 files changed, 22 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