@@ -102,9 +102,23 @@ class TypeSpecializer extends MiniPhaseTransform with InfoTransformer {
102
102
(implicit ctx : Context ): List [Symbol ] = {
103
103
val newSym =
104
104
ctx.newSymbol(decl.owner, (decl.name + names.mkString).toTermName,
105
- decl.flags | Flags .Synthetic ,
106
- poly.derivedPolyType(poly.paramNames, poly.paramBounds,
107
- poly.instantiate(instantiations.toList)))
105
+ decl.flags | Flags .Synthetic , poly.instantiate(instantiations.toList))
106
+
107
+ /* The following generated symbols which kept type bounds. It served, as illustrated by the `this_specialization`
108
+ * test, as a way of keeping type bounds when instantiating a `this` referring to a generic class. However,
109
+ * because type bounds are not transitive, this did not work out and we introduced casts instead.
110
+ *
111
+ * ctx.newSymbol(decl.owner, (decl.name + names.mkString).toTermName,
112
+ * decl.flags | Flags.Synthetic,
113
+ * poly.derivedPolyType(poly.paramNames,
114
+ * (poly.paramBounds zip instantiations).map
115
+ * {case (bounds, instantiation) =>
116
+ * TypeBounds(bounds.lo, AndType(bounds.hi, instantiation))},
117
+ * poly.instantiate(indices, instantiations)
118
+ * )
119
+ * )
120
+ */
121
+
108
122
val map = newSymbolMap.getOrElse(decl, mutable.HashMap .empty)
109
123
map.put(instantiations, newSym)
110
124
newSymbolMap.put(decl, map)
@@ -152,39 +166,31 @@ class TypeSpecializer extends MiniPhaseTransform with InfoTransformer {
152
166
def specialize (decl : Symbol ): List [Tree ] = {
153
167
if (newSymbolMap.contains(decl)) {
154
168
val declSpecs = newSymbolMap(decl)
155
- var failedSpec : List [Symbol ] = List ()
156
169
val newSyms = declSpecs.values.toList
157
170
val instantiations = declSpecs.keys.toArray
158
171
var index = - 1
159
172
println(s " specializing ${tree.symbol} for $origTParams" )
160
- /* val attempted = newSyms.zip( */ newSyms.map { newSym =>
173
+ newSyms.map { newSym =>
161
174
index += 1
162
175
polyDefDef(newSym.asTerm, { tparams => vparams => {
163
- // assert(tparams.isEmpty)
164
-
165
176
val tmap : (Tree => Tree ) = _ match {
166
177
case Return (t, from) if from.symbol == tree.symbol => Return (t, ref(newSym))
167
178
case t : TypeApply => transformTypeApply(t)
179
+ case t : Apply => transformApply(t)
168
180
case t => t
169
181
}
170
182
171
183
new TreeTypeMap (
172
184
treeMap = tmap,
173
- typeMap = _ /* match {
174
- case t if !poly.bounds.contains(t) => {
175
- failedSpec = newSym :: failedSpec
176
- t
177
- }
178
- case t => t*/
185
+ typeMap = _
179
186
.substDealias(origTParams, instantiations(index))
180
187
.subst(origVParams, vparams.flatten.map(_.tpe))
181
188
,
182
189
oldOwners = tree.symbol :: Nil ,
183
190
newOwners = newSym :: Nil
184
191
).transform(tree.rhs)
185
192
}})
186
- }// )
187
- // attempted.filterNot(a => failedSpec.contains(a._1)).map(_._2)
193
+ }
188
194
} else Nil
189
195
}
190
196
val specialized_trees = specialize(tree.symbol)
@@ -194,20 +200,55 @@ class TypeSpecializer extends MiniPhaseTransform with InfoTransformer {
194
200
}
195
201
196
202
override def transformTypeApply (tree : tpd.TypeApply )(implicit ctx : Context , info : TransformerInfo ): Tree = {
203
+ val TypeApply (fun, _) = tree
204
+ if (fun.tpe.isParameterless) rewireTree(tree)
205
+ tree
206
+ }
197
207
208
+ override def transformApply (tree : Apply )(implicit ctx : Context , info : TransformerInfo ): Tree = {
209
+ val Apply (fun, args) = tree
210
+ fun match {
211
+ case fun : TypeApply => {
212
+ println(
213
+ s """
214
+ |args -> ${args}
215
+
216
+ |f.fun -> ${fun.fun.tree}
217
+ """ .stripMargin)
218
+
219
+ val newFun = rewireTree(fun)
220
+ if (fun ne newFun) {
221
+ val b = (args zip newFun.tpe.firstParamTypes)
222
+ val a = b.map{
223
+ case (arg, tpe) =>
224
+ arg.ensureConforms(tpe)
225
+ }
226
+ Apply (newFun,a)
227
+ /* zip (instantiations zip paramTypes)).map{
228
+ case (argType, (specType, castType)) => argType.ensureConforms(specType)})*/
229
+ } else tree
230
+ }
231
+ case _ => tree
232
+ }
233
+ }
234
+
235
+ def rewireTree (tree : Tree )(implicit ctx : Context ): Tree = {
236
+ assert(tree.isInstanceOf [TypeApply ])
198
237
val TypeApply (fun,args) = tree
199
238
if (newSymbolMap.contains(fun.symbol)){
200
239
val newSymInfos = newSymbolMap(fun.symbol)
201
240
val betterDefs = newSymInfos.filter(x => (x._1 zip args).forall{a =>
202
- val specializedType = a._1
203
- val argType = a._2
241
+ val specializedType = a._1
242
+ val argType = a._2
204
243
argType.tpe <:< specializedType
205
244
}).toList
206
245
207
- if (betterDefs.length > 1 ) ctx.debuglog(" Several specialized variants fit." )
208
- // assert(betterDefs.length < 2) // TODO: How to select the best if there are several ?
246
+ if (betterDefs.length > 1 ) {
247
+ ctx.debuglog(" Several specialized variants fit." )
248
+ tree
249
+ }
209
250
210
- if (betterDefs.nonEmpty) {
251
+ else if (betterDefs.nonEmpty) {
211
252
val best = betterDefs.head
212
253
println(s " method ${fun.symbol.name} of ${fun.symbol.owner} rewired to specialized variant with type ( ${best._1}) " )
213
254
val prefix = fun match {
@@ -225,4 +266,4 @@ class TypeSpecializer extends MiniPhaseTransform with InfoTransformer {
225
266
} else tree
226
267
} else tree
227
268
}
228
- }
269
+ }
0 commit comments