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