@@ -15,43 +15,65 @@ class SpecializeFunctions extends MiniPhaseTransform with InfoTransformer {
15
15
import ast .tpd ._
16
16
val phaseName = " specializeFunctions"
17
17
18
+ private [this ] var _blacklistedSymbols : List [Symbol ] = _
19
+
20
+ private def blacklistedSymbols (implicit ctx : Context ): List [Symbol ] = {
21
+ if (_blacklistedSymbols eq null ) _blacklistedSymbols = List (
22
+ ctx.getClassIfDefined(" scala.math.Ordering" ).asClass.membersNamed(" Ops" .toTypeName).first.symbol
23
+ )
24
+
25
+ _blacklistedSymbols
26
+ }
27
+
18
28
/** Transforms the type to include decls for specialized applys and replace
19
29
* the class parents with specialized versions.
20
30
*/
21
31
def transformInfo (tp : Type , sym : Symbol )(implicit ctx : Context ) = tp match {
22
- case tp : ClassInfo if ! sym.is(Flags .Package ) => {
32
+ case tp : ClassInfo
33
+ if ! sym.is(Flags .Package ) &&
34
+ ! blacklistedSymbols.contains(sym) &&
35
+ (tp.decls ne EmptyScope )
36
+ => {
23
37
var newApplys : List [Symbol ] = Nil
24
38
25
39
val newParents = tp.parents.mapConserve { parent =>
26
- if (defn.isPlainFunctionClass(parent.symbol)) {
27
- val typeParams = tp.typeRef.baseArgTypes(parent.classSymbol)
28
- val interface = specInterface(typeParams)
29
-
30
- if (interface.exists) {
31
- val specializedApply : Symbol = {
32
- val specializedMethodName = specializedName(nme.apply, typeParams)
33
- ctx.newSymbol(
34
- sym,
35
- specializedMethodName,
36
- Flags .Override | Flags .Method ,
37
- interface.info.decls.lookup(specializedMethodName).info
38
- )
40
+ List (0 , 1 , 2 , 3 ).flatMap { arity =>
41
+ val func = defn.FunctionClass (arity)
42
+ if (! parent.isRef(func)) Nil
43
+ else {
44
+ val typeParams = tp.typeRef.baseArgInfos(func)
45
+ val interface = specInterface(typeParams)
46
+
47
+ if (interface.exists) {
48
+ val specializedApply = {
49
+ val specializedMethodName = specializedName(nme.apply, typeParams)
50
+ ctx.newSymbol(
51
+ sym,
52
+ specializedMethodName,
53
+ Flags .Override | Flags .Method ,
54
+ interface.info.decls.lookup(specializedMethodName).info
55
+ )
56
+ }
57
+ newApplys = specializedApply :: newApplys
58
+ List (interface.typeRef)
39
59
}
40
-
41
- newApplys = specializedApply :: newApplys
42
- interface.typeRef
60
+ else Nil
43
61
}
44
- else parent
45
62
}
46
- else parent
63
+ .headOption
64
+ .getOrElse(parent)
47
65
}
48
66
49
- def newDecls = newApplys.foldLeft(tp.decls.cloneScope) {
50
- (scope, sym) => scope.enter(sym); scope
51
- }
67
+ def newDecls =
68
+ if (newApplys.isEmpty) tp.decls
69
+ else newApplys.foldLeft(tp.decls.cloneScope) {
70
+ (scope, sym) => scope.enter(sym); scope
71
+ }
52
72
53
- if (newApplys eq Nil ) tp
54
- else tp.derivedClassInfo(classParents = newParents, decls = newDecls)
73
+ tp.derivedClassInfo(
74
+ classParents = newParents,
75
+ decls = newDecls
76
+ )
55
77
}
56
78
57
79
case _ => tp
@@ -63,10 +85,10 @@ class SpecializeFunctions extends MiniPhaseTransform with InfoTransformer {
63
85
* template body.
64
86
*/
65
87
override def transformTemplate (tree : Template )(implicit ctx : Context , info : TransformerInfo ) = {
66
- val buf = new mutable.ListBuffer [Tree ]
88
+ val applyBuf = new mutable.ListBuffer [Tree ]
67
89
val newBody = tree.body.mapConserve {
68
90
case dt : DefDef if dt.name == nme.apply && dt.vparamss.length == 1 => {
69
- val specializedApply = ctx.owner .info.decls.lookup {
91
+ val specializedApply = tree.symbol.enclosingClass .info.decls.lookup {
70
92
specializedName(
71
93
nme.apply,
72
94
dt.vparamss.head.map(_.symbol.info) :+ dt.tpe.widen.finalResultType
@@ -82,7 +104,7 @@ class SpecializeFunctions extends MiniPhaseTransform with InfoTransformer {
82
104
.subst(dt.vparamss.flatten.map(_.symbol), vrefss.flatten.map(_.symbol))
83
105
})
84
106
85
- buf += specializedDecl
107
+ applyBuf += specializedDecl
86
108
87
109
// create a forwarding to the specialized apply
88
110
cpy.DefDef (dt)(rhs = {
@@ -95,29 +117,52 @@ class SpecializeFunctions extends MiniPhaseTransform with InfoTransformer {
95
117
case x => x
96
118
}
97
119
98
- val newParents = tree.parents.mapConserve { parent =>
99
- if (defn.isPlainFunctionClass(parent.symbol)) {
100
- val typeParams = tree.tpe.baseArgTypes(parent.symbol)
101
- val interface = specInterface(typeParams)
120
+ val missing : List [TypeTree ] = List (0 , 1 , 2 , 3 ).flatMap { arity =>
121
+ val func = defn.FunctionClass (arity)
122
+ val tr = tree.symbol.enclosingClass.typeRef
102
123
103
- if (interface.exists) TypeTree (interface.info)
104
- else parent
105
- }
106
- else parent
107
- }
124
+ if (! tr.parents.exists(_.isRef(func))) Nil
125
+ else {
126
+ val typeParams = tr.baseArgInfos(func)
127
+ val interface = specInterface(typeParams)
128
+
129
+ if (interface.exists) List (interface.info)
130
+ else Nil
131
+ }
132
+ }.map(TypeTree )
108
133
109
- cpy.Template (tree)(parents = newParents, body = buf.toList ++ newBody)
134
+ cpy.Template (tree)(
135
+ parents = tree.parents ++ missing,
136
+ body = applyBuf.toList ++ newBody
137
+ )
110
138
}
111
139
112
140
/** Dispatch to specialized `apply`s in user code when available */
113
141
override def transformApply (tree : Apply )(implicit ctx : Context , info : TransformerInfo ) =
114
142
tree match {
115
- case Apply (select @ Select (id, nme.apply), args) => {
116
- val params = args.map(_.tpe) :+ tree.tpe
143
+ case app @ Apply (fun, args)
144
+ if fun.symbol.name == nme.apply &&
145
+ fun.symbol.owner.derivesFrom(defn.FunctionClass (args.length))
146
+ => {
147
+ val params = (fun.tpe.widen.firstParamTypes :+ tree.tpe).map(_.widenSingleton.dealias)
117
148
val specializedApply = specializedName(nme.apply, params)
118
149
119
- if (tree.fun.symbol.owner.info.member(specializedApply).exists)
120
- tpd.Apply (tpd.Select (id, specializedApply), args)
150
+ if (! params.exists(_.isInstanceOf [ExprType ]) && defn.FunctionClass (args.length).info.member(specializedApply).exists) {
151
+ val newSel = fun match {
152
+ case Select (qual, _) =>
153
+ qual.select(specializedApply)
154
+ case _ => {
155
+ (fun.tpe: @ unchecked) match {
156
+ case TermRef (prefix : ThisType , name) =>
157
+ tpd.This (prefix.cls).select(specializedApply)
158
+ case TermRef (prefix : NamedType , name) =>
159
+ tpd.ref(prefix).select(specializedApply)
160
+ }
161
+ }
162
+ }
163
+
164
+ newSel.appliedToArgs(args)
165
+ }
121
166
else tree
122
167
}
123
168
case _ => tree
@@ -128,7 +173,7 @@ class SpecializeFunctions extends MiniPhaseTransform with InfoTransformer {
128
173
129
174
@ inline private def specInterface (typeParams : List [Type ])(implicit ctx : Context ) = {
130
175
val specName =
131
- (" JFunction" .toTermName ++ (typeParams.length - 1 ))
176
+ (" JFunction" + (typeParams.length - 1 )).toTermName
132
177
.specializedFor(typeParams, typeParams.map(_.typeSymbol.name), Nil , Nil )
133
178
134
179
ctx.getClassIfDefined(" scala.compat.java8." .toTermName ++ specName)
0 commit comments