@@ -20,28 +20,28 @@ class SpecializeFunctions extends MiniPhase with InfoTransformer {
2020
2121 /** Transforms the type to include decls for specialized applys */
2222 override def transformInfo (tp : Type , sym : Symbol )(implicit ctx : Context ) = tp match {
23- case tp : ClassInfo if ! sym.is(Flags .Package ) && (tp.decls ne EmptyScope ) =>
23+ case tp : ClassInfo if ! sym.is(Flags .Package ) && (tp.decls ne EmptyScope ) && derivesFromFn012(sym) =>
2424 var newApplys = Map .empty[Name , Symbol ]
2525
26- tp.parents.foreach { parent =>
27- List (0 , 1 , 2 ).foreach { arity =>
28- val func = defn.FunctionClass (arity)
29- if (parent.derivesFrom(func)) {
30- val typeParams = tp.cls.typeRef.baseType(func).argInfos
31- val isSpecializable =
32- defn.isSpecializableFunction(
33- parent.classSymbol.asClass,
34- typeParams.init,
35- typeParams.last
36- )
37-
38- if (isSpecializable && tp.decls.lookup(nme.apply).exists) {
39- val interface = specInterface(typeParams)
40- val specializedMethodName = nme.apply.specializedFunction(typeParams.last, typeParams.init)
41- newApplys += (specializedMethodName -> interface)
42- }
26+ var arity = 0
27+ while (arity < 3 ) {
28+ val func = defn.FunctionClass (arity)
29+ if (tp.derivesFrom(func)) {
30+ val typeParams = tp.cls.typeRef.baseType(func).argInfos
31+ val isSpecializable =
32+ defn.isSpecializableFunction(
33+ sym.asClass,
34+ typeParams.init,
35+ typeParams.last
36+ )
37+
38+ if (isSpecializable && tp.decls.lookup(nme.apply).exists) {
39+ val interface = specInterface(typeParams)
40+ val specializedMethodName = nme.apply.specializedFunction(typeParams.last, typeParams.init)
41+ newApplys += (specializedMethodName -> interface)
4342 }
4443 }
44+ arity += 1
4545 }
4646
4747 def newDecls =
@@ -68,39 +68,41 @@ class SpecializeFunctions extends MiniPhase with InfoTransformer {
6868 * in the template body.
6969 */
7070 override def transformTemplate (tree : Template )(implicit ctx : Context ) = {
71- val applyBuf = new mutable.ListBuffer [Tree ]
72- val newBody = tree.body.mapConserve {
73- case dt : DefDef if dt.name == nme.apply && dt.vparamss.length == 1 =>
74- val cls = tree.symbol.enclosingClass.asClass
75- val typeParams = dt.vparamss.head.map(_.symbol.info)
76- val retType = dt.tpe.widen.finalResultType
77-
78- val specName = specializedName(nme.apply, typeParams :+ retType)
79- val specializedApply = cls.info.decls.lookup(specName)
80- if (specializedApply.exists) {
81- val apply = specializedApply.asTerm
82- val specializedDecl =
83- polyDefDef(apply, trefs => vrefss => {
84- dt.rhs
85- .changeOwner(dt.symbol, apply)
86- .subst(dt.vparamss.flatten.map(_.symbol), vrefss.flatten.map(_.symbol))
71+ val cls = tree.symbol.enclosingClass.asClass
72+ if (derivesFromFn012(cls)) {
73+ val applyBuf = new mutable.ListBuffer [Tree ]
74+ val newBody = tree.body.mapConserve {
75+ case dt : DefDef if dt.name == nme.apply && dt.vparamss.length == 1 =>
76+ val typeParams = dt.vparamss.head.map(_.symbol.info)
77+ val retType = dt.tpe.widen.finalResultType
78+
79+ val specName = specializedName(nme.apply, typeParams :+ retType)
80+ val specializedApply = cls.info.decls.lookup(specName)
81+ if (specializedApply.exists) {
82+ val apply = specializedApply.asTerm
83+ val specializedDecl =
84+ polyDefDef(apply, trefs => vrefss => {
85+ dt.rhs
86+ .changeOwner(dt.symbol, apply)
87+ .subst(dt.vparamss.flatten.map(_.symbol), vrefss.flatten.map(_.symbol))
88+ })
89+ applyBuf += specializedDecl
90+
91+ // create a forwarding to the specialized apply
92+ cpy.DefDef (dt)(rhs = {
93+ tpd
94+ .ref(apply)
95+ .appliedToArgs(dt.vparamss.head.map(vparam => ref(vparam.symbol)))
8796 })
88- applyBuf += specializedDecl
97+ } else dt
8998
90- // create a forwarding to the specialized apply
91- cpy.DefDef (dt)(rhs = {
92- tpd
93- .ref(apply)
94- .appliedToArgs(dt.vparamss.head.map(vparam => ref(vparam.symbol)))
95- })
96- } else dt
97-
98- case x => x
99- }
99+ case x => x
100+ }
100101
101- cpy.Template (tree)(
102- body = applyBuf.toList ++ newBody
103- )
102+ cpy.Template (tree)(
103+ body = applyBuf.toList ::: newBody
104+ )
105+ } else tree
104106 }
105107
106108 /** Dispatch to specialized `apply`s in user code when available */
@@ -146,4 +148,9 @@ class SpecializeFunctions extends MiniPhase with InfoTransformer {
146148
147149 private def specInterface (typeParams : List [Type ])(implicit ctx : Context ) =
148150 ctx.getClassIfDefined(functionName(typeParams).specializedFunction(typeParams.last, typeParams.init))
151+
152+ private def derivesFromFn012 (sym : Symbol )(implicit ctx : Context ): Boolean =
153+ sym.derivesFrom(defn.FunctionClass (0 )) ||
154+ sym.derivesFrom(defn.FunctionClass (1 )) ||
155+ sym.derivesFrom(defn.FunctionClass (2 ))
149156}
0 commit comments