Skip to content

Commit f3beaa8

Browse files
committed
Optimize Array.apply only when ClassTag is statically known
1 parent 772f5b9 commit f3beaa8

File tree

4 files changed

+28
-3
lines changed

4 files changed

+28
-3
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,8 @@ class Definitions {
755755
@threadUnsafe lazy val ClassTagType: TypeRef = ctx.requiredClassRef("scala.reflect.ClassTag")
756756
def ClassTagClass(implicit ctx: Context): ClassSymbol = ClassTagType.symbol.asClass
757757
def ClassTagModule(implicit ctx: Context): Symbol = ClassTagClass.companionModule
758+
@threadUnsafe lazy val ClassTagModule_applyR: TermRef = ClassTagModule.requiredMethodRef(nme.apply)
759+
def ClassTagModule_apply(implicit ctx: Context): Symbol = ClassTagModule_applyR.symbol
758760

759761
@threadUnsafe lazy val QuotedExprType: TypeRef = ctx.requiredClassRef("scala.quoted.Expr")
760762
def QuotedExprClass(implicit ctx: Context): ClassSymbol = QuotedExprType.symbol.asClass

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

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import StdNames._
1010
import ast.Trees._
1111
import dotty.tools.dotc.ast.tpd
1212

13+
import scala.reflect.ClassTag
14+
1315

1416
/** This phase rewrites calls to `Array.apply` to primitive array instantion.
1517
*
@@ -38,9 +40,27 @@ class ArrayApply extends MiniPhase {
3840
} else tree
3941
}
4042

41-
// Only optimize when classtag is `ClassTag.apply` or `ClassTag.{Byte, Boolean, ...}`
42-
private def elideClassTag(ct: Tree)(implicit ctx: Context): Boolean = {
43-
ct.symbol.maybeOwner.companionModule == defn.ClassTagModule
43+
/** Only optimize when classtag if it is one of
44+
* - `ClassTag.apply(classOf[X])`
45+
* - `ClassTag.apply(java.lang.XYZ.Type)`
46+
* - `ClassTag.{Byte, Boolean, ...}`
47+
*/
48+
private def elideClassTag(ct: Tree)(implicit ctx: Context): Boolean = ct match {
49+
case Apply(_, rc :: Nil) if ct.symbol == defn.ClassTagModule_apply =>
50+
rc match {
51+
case _: Literal => true // classOf[X]
52+
case rc: RefTree if rc.name == nme.TYPE_ =>
53+
val owner = rc.symbol.maybeOwner.companionModule
54+
owner == defn.BoxedBooleanModule || owner == defn.BoxedByteModule ||
55+
owner == defn.BoxedShortModule || owner == defn.BoxedCharModule ||
56+
owner == defn.BoxedIntModule || owner == defn.BoxedLongModule ||
57+
owner == defn.BoxedFloatModule || owner == defn.BoxedDoubleModule ||
58+
owner == defn.BoxedUnitModule
59+
case _ => false
60+
}
61+
case Apply(ctm: RefTree, _) if ctm.symbol.maybeOwner.companionModule == defn.ClassTagModule =>
62+
nme.ScalaValueNames.contains(ctm.name)
63+
case _ => false
4464
}
4565

4666
object CleanTree {

tests/run/i502.check

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
Ok
22
foo
3+
bar

tests/run/i502.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,6 @@ object Test extends App {
1111
}
1212

1313
Array[Int](1, 2)({println("foo"); the[ClassTag[Int]]})
14+
15+
Array[Int](1, 2)(ClassTag.apply({ println("bar"); classOf[Int]}))
1416
}

0 commit comments

Comments
 (0)