@@ -34,38 +34,38 @@ class TypeSpecializer extends MiniPhaseTransform with InfoTransformer {
34
34
35
35
/**
36
36
* Methods requested for specialization
37
- * Generic Symbol => List[ (position in type args list , specialized type requested) ]
37
+ * Generic Symbol => List[ (position in list of args , specialized type requested) ]
38
38
*/
39
39
private val specializationRequests : mutable.HashMap [Symbols .Symbol , List [(Int , List [Type ])]] = mutable.HashMap .empty
40
40
41
41
/**
42
- * A list of instantiation values of generics (helps with recursive polymorphic methods)
42
+ * A list of instantiation values of generics (for recursive polymorphic methods)
43
43
*/
44
44
private val genericToInstantiation : mutable.HashMap [Symbols .Symbol , Type ] = mutable.HashMap .empty
45
45
46
46
/**
47
47
* A map that links symbols to their specialized variants.
48
48
* Each symbol maps to another map, from the list of specialization types to the specialized symbol.
49
- * Generic symbol => Map[ Tuple(position in type args list, specialized Type) => Specialized Symbol ]
49
+ * Generic symbol =>
50
+ * Map{ List of [ Tuple(position in list of args, specialized Type) ] for each variant => Specialized Symbol }
50
51
*/
51
52
private val newSymbolMap : mutable.HashMap [Symbol , mutable.HashMap [List [(Int , Type )], Symbols .Symbol ]] = mutable.HashMap .empty
52
53
53
54
/**
54
55
* A map from specialised symbols to the indices of their remaining generic types
55
56
*/
56
- private val newSymbolsGenericIndices : mutable.HashMap [Symbol , List [Int ]] = mutable.HashMap .empty
57
+ private val newSymToGenIndices : mutable.HashMap [Symbol , List [Int ]] = mutable.HashMap .empty
57
58
58
59
/**
59
60
* A list of symbols gone through the specialisation pipeline
60
61
* Is used to make calls to transformInfo idempotent
61
62
*/
62
- private val specialized : ListBuffer [Symbol ] = ListBuffer .empty
63
+ private val processed : ListBuffer [Symbol ] = ListBuffer .empty
63
64
64
65
def allowedToSpecialize (sym : Symbol , numOfTypes : Int )(implicit ctx : Context ) =
65
66
numOfTypes > 0 &&
66
67
sym.name != nme.asInstanceOf_ &&
67
68
! newSymbolMap.contains(sym) &&
68
- ! sym.name.toString.contains(" $sp" ) &&
69
69
! (sym is Flags .JavaDefined ) &&
70
70
! sym.isPrimaryConstructor
71
71
@@ -88,7 +88,8 @@ class TypeSpecializer extends MiniPhaseTransform with InfoTransformer {
88
88
def requestedSpecialization (decl : Symbol )(implicit ctx : Context ): Boolean =
89
89
ctx.settings.Yspecialize .value != 0 || specializationRequests.contains(decl)
90
90
91
- def registerSpecializationRequest (method : Symbols .Symbol )(index : Int , arguments : List [Type ])(implicit ctx : Context ) = {
91
+ def registerSpecializationRequest (method : Symbols .Symbol )(index : Int , arguments : List [Type ])
92
+ (implicit ctx : Context ) = {
92
93
if (ctx.phaseId > this .treeTransformPhase.id)
93
94
assert(ctx.phaseId <= this .treeTransformPhase.id)
94
95
val prev = specializationRequests.getOrElse(method, List .empty)
@@ -104,7 +105,7 @@ class TypeSpecializer extends MiniPhaseTransform with InfoTransformer {
104
105
}
105
106
106
107
def specializeMethods (sym : Symbol ) = {
107
- specialized += sym
108
+ processed += sym
108
109
sym.info match {
109
110
case classInfo : ClassInfo =>
110
111
val newDecls = classInfo.decls
@@ -114,7 +115,7 @@ class TypeSpecializer extends MiniPhaseTransform with InfoTransformer {
114
115
.flatMap(decl => {
115
116
decl.info.widen match {
116
117
case poly : PolyType if allowedToSpecialize(decl.symbol, poly.paramNames.length) =>
117
- generateMethodSpecializations(getSpecTypes(decl, poly))( List .empty, poly, decl)
118
+ generateMethodSpecializations(getSpecTypes(decl, poly), List .empty)( poly, decl)
118
119
case _ => Nil
119
120
}
120
121
})
@@ -128,54 +129,59 @@ class TypeSpecializer extends MiniPhaseTransform with InfoTransformer {
128
129
}
129
130
else if (requestedSpecialization(sym) &&
130
131
allowedToSpecialize(sym, poly.paramNames.length)) {
131
- generateMethodSpecializations(getSpecTypes(sym, poly))( List .empty, poly, sym)
132
+ generateMethodSpecializations(getSpecTypes(sym, poly), List .empty)( poly, sym)
132
133
tp
133
134
}
134
135
else tp
135
136
case _ => tp
136
137
}
137
138
}
138
139
139
- def generateMethodSpecializations (specTypes : List [(Int , List [Type ])])
140
- (instantiations : List [( Int , Type )], poly : PolyType , decl : Symbol )
140
+ def generateMethodSpecializations (specTypes : List [(Int , List [Type ])], instantiations : List [( Int , Type )] )
141
+ (poly : PolyType , decl : Symbol )
141
142
(implicit ctx : Context ): List [Symbol ] = {
142
143
if (specTypes.nonEmpty) {
143
144
specTypes.head match {
144
145
case (i, tpes) if tpes.nonEmpty =>
145
146
tpes.flatMap(tpe =>
146
- generateMethodSpecializations(specTypes.tail)(( i, tpe) :: instantiations, poly, decl)
147
+ generateMethodSpecializations(specTypes.tail, ( i, tpe) :: instantiations)( poly, decl)
147
148
)
148
149
case (i, nil) =>
149
- generateMethodSpecializations(specTypes.tail)(instantiations, poly, decl)
150
+ generateMethodSpecializations(specTypes.tail, instantiations)( poly, decl)
150
151
}
151
152
}
152
153
else {
153
154
if (instantiations.isEmpty) Nil
154
155
else generateSpecializedSymbol(instantiations.reverse, poly, decl) :: Nil
155
156
}
156
157
}
158
+
157
159
def generateSpecializedSymbol (instantiations : List [(Int , Type )], poly : PolyType , decl : Symbol )
158
160
(implicit ctx : Context ): Symbol = {
159
161
val indices = instantiations.map(_._1)
160
162
val instanceTypes = instantiations.map(_._2)
161
- val newSym = ctx.newSymbol(decl.owner, NameOps .NameDecorator (decl.name).specializedFor(Nil , Nil , instanceTypes, instanceTypes.map(_.asInstanceOf [NamedType ].name)),
162
- decl.flags | Flags .Synthetic , {
163
- if (indices.length != poly.paramNames.length) // Partial Specialisation case
164
- poly.instantiate(indices, instanceTypes) // Returns a PolyType with uninstantiated types kept generic
165
- else
166
- poly.instantiate(instanceTypes) // Returns a MethodType, as no polymorphic types remains
167
- })
163
+ val newSym = ctx.newSymbol(
164
+ decl.owner,
165
+ NameOps .NameDecorator (decl.name)
166
+ .specializedFor(Nil , Nil , instanceTypes, instanceTypes.map(_.asInstanceOf [NamedType ].name)),
167
+ decl.flags | Flags .Synthetic ,
168
+ { if (indices.length != poly.paramNames.length) // Partial Specialisation case
169
+ poly.instantiate(indices, instanceTypes) // Returns a PolyType with uninstantiated types kept generic
170
+ else
171
+ poly.instantiate(instanceTypes) // Returns a MethodType, no polymorphic type remains
172
+ }
173
+ )
168
174
169
175
val map = newSymbolMap.getOrElse(decl, mutable.HashMap .empty)
170
176
map.put(instantiations, newSym)
171
177
newSymbolMap.put(decl, map)
172
178
173
- newSymbolsGenericIndices .put(newSym, indices)
179
+ newSymToGenIndices .put(newSym, indices)
174
180
175
181
newSym
176
182
}
177
183
178
- if (! specialized .contains(sym) &&
184
+ if (! processed .contains(sym) &&
179
185
(sym ne defn.ScalaPredefModule .moduleClass) &&
180
186
! (sym is Flags .JavaDefined ) &&
181
187
! (sym is Flags .Scala2x ) &&
@@ -204,50 +210,53 @@ class TypeSpecializer extends MiniPhaseTransform with InfoTransformer {
204
210
case (_, i) => instantiation.getOrElse(i, {
205
211
holePos += 1
206
212
PolyParam (pt, holePos)
207
- }
208
- ).widen
213
+ }).widen
209
214
}
210
215
}
211
216
212
217
if (newSymbolMap.contains(decl)) {
213
- val declSpecs = newSymbolMap(decl)
214
- val newSyms = declSpecs .values.toList
215
- val instantiations = declSpecs .keys.toArray
218
+ val specInfo = newSymbolMap(decl)
219
+ val newSyms = specInfo .values.toList
220
+ val instantiationss = specInfo .keys.toArray
216
221
var index = - 1
217
222
ctx.debuglog(s " specializing ${tree.symbol} for $origTParams" )
218
223
newSyms.map { newSym =>
219
224
index += 1
220
225
val newSymType = newSym.info.widenDealias
221
226
polyDefDef(newSym.asTerm, { tparams => vparams => {
222
227
val instTypes = newSymType match {
223
- case pt : PolyType => makeTypesList(origTParams, instantiations(index).toMap, pt)
224
- case _ => instantiations(index).map(_._2)
228
+ case pt : PolyType =>
229
+ makeTypesList(origTParams, instantiationss(index).toMap, pt) // Will add missing PolyParams
230
+ case _ => instantiationss(index).map(_._2)
225
231
}
226
232
227
233
val treemap : (Tree => Tree ) = _ match {
228
234
case Return (t, from) if from.symbol == tree.symbol => Return (t, ref(newSym))
229
235
case t : TypeApply =>
230
- (origTParams zip instTypes).foreach(x => genericToInstantiation.put(x._1, x._2))
236
+ (origTParams zip instTypes)
237
+ .foreach{case (genTpe, instTpe) => genericToInstantiation.put(genTpe, instTpe)}
231
238
transformTypeApply(t)
232
239
case t : Apply =>
233
- (origTParams zip instTypes).foreach(x => genericToInstantiation.put(x._1, x._2))
240
+ (origTParams zip instTypes)
241
+ .foreach{case (genTpe, instTpe) => genericToInstantiation.put(genTpe, instTpe)}
234
242
transformApply(t)
235
243
case t => t
236
244
}
237
245
238
246
val abstractPolyType = tree.symbol.info.widenDealias.asInstanceOf [PolyType ]
247
+ val vparamTpes = vparams.flatten.map(_.tpe)
239
248
val typemap = new TypeMap {
240
249
override def apply (tp : Type ): Type = {
241
250
val t = mapOver(tp)
242
251
.substDealias(origTParams, instTypes)
243
252
.substParams(abstractPolyType, instTypes)
244
- .subst(origVParams, vparams.flatten.map(_.tpe) )
253
+ .subst(origVParams, vparamTpes )
245
254
newSymType match {
246
255
case mt : MethodType if tparams.isEmpty =>
247
- t.substParams(newSymType.asInstanceOf [MethodType ], vparams.flatten.map(_.tpe) )
256
+ t.substParams(newSymType.asInstanceOf [MethodType ], vparamTpes )
248
257
case pt : PolyType =>
249
258
t.substParams(newSymType.asInstanceOf [PolyType ], tparams)
250
- .substParams(newSymType.resultType.asInstanceOf [MethodType ], vparams.flatten.map(_.tpe) )
259
+ .substParams(newSymType.resultType.asInstanceOf [MethodType ], vparamTpes )
251
260
case _ => t
252
261
}
253
262
}
@@ -265,11 +274,13 @@ class TypeSpecializer extends MiniPhaseTransform with InfoTransformer {
265
274
override def transform (tree1 : Tree )(implicit ctx : Context ) = super .transform(tree1) match {
266
275
case t @ Apply (fun, args) =>
267
276
assert(sameLength(args, fun.tpe.widen.firstParamTypes),
268
- s " Wrong number of parameters. Expected: ${fun.tpe.widen.firstParamTypes.length}. Found: ${args.length}" )
277
+ s " Wrong number of parameters. " +
278
+ s " Expected: ${fun.tpe.widen.firstParamTypes.length}. " +
279
+ s " Found: ${args.length}" )
269
280
val newArgs = (args zip fun.tpe.widen.firstParamTypes).map{
270
- case (tr , tpe) =>
281
+ case (arg , tpe) =>
271
282
assert(tpe.widen ne NoType , " Bad cast when specializing" )
272
- tr .ensureConforms(typemap(tpe.widen))
283
+ arg .ensureConforms(typemap(tpe.widen))
273
284
}
274
285
if (sameTypes(args, newArgs)) {
275
286
t
@@ -308,23 +319,22 @@ class TypeSpecializer extends MiniPhaseTransform with InfoTransformer {
308
319
assert(tree.isInstanceOf [TypeApply ])
309
320
val TypeApply (fun,args) = tree
310
321
if (newSymbolMap.contains(fun.symbol)){
311
- val newSymInfos = newSymbolMap(fun.symbol)
312
- val betterDefs = newSymInfos.filter(
313
- x => {
314
- val instantiation = x._1
315
- instantiation.forall { x =>
316
- val ord = x._1
317
- val tp = x._2
318
- args(ord).tpe <:< tp
319
- }}).toList
322
+ val newSymInfo = newSymbolMap(fun.symbol)
323
+ val betterDefs = newSymInfo.filter{
324
+ case (instantiations, symbol) => {
325
+ instantiations.forall {
326
+ case (ord, specTpe) =>
327
+ args(ord).tpe <:< specTpe
328
+ }}}.toList
320
329
321
330
if (betterDefs.length > 1 ) {
322
- ctx.debuglog(s " Several specialized variants fit for ${fun.symbol.name} of ${fun.symbol.owner}. Defaulting to no specialization. " )
331
+ ctx.debuglog(s " Several specialized variants fit for ${fun.symbol.name} of ${fun.symbol.owner}. " +
332
+ s " Defaulting to no specialization. " )
323
333
tree
324
334
}
325
335
326
336
else if (betterDefs.nonEmpty) {
327
- val bestDef = betterDefs.head
337
+ val newFunSym = betterDefs.head._2
328
338
ctx.debuglog(s " method ${fun.symbol.name} of ${fun.symbol.owner} rewired to specialized variant " )
329
339
val prefix = fun match {
330
340
case Select (pre, name) =>
@@ -336,8 +346,8 @@ class TypeSpecializer extends MiniPhaseTransform with InfoTransformer {
336
346
else EmptyTree
337
347
case _ => EmptyTree
338
348
}
339
- if (prefix ne EmptyTree ) prefix.select(bestDef._2 )
340
- else ref(bestDef._2 )
349
+ if (prefix ne EmptyTree ) prefix.select(newFunSym )
350
+ else ref(newFunSym )
341
351
} else tree
342
352
} else tree
343
353
}
@@ -357,8 +367,10 @@ class TypeSpecializer extends MiniPhaseTransform with InfoTransformer {
357
367
if (fun ne newFun) {
358
368
newFun.symbol.info.widenDealias match {
359
369
case pt : PolyType => // Need to apply types to the remaining generics first
360
- val tpeOfRemainingGenerics = typeArgs.zipWithIndex.filterNot(x => newSymbolsGenericIndices(newFun.symbol).contains(x._2)).map(_._1)
361
- assert(tpeOfRemainingGenerics.nonEmpty, s " Remaining generics on ${newFun.symbol.name} not properly instantiated: missing types " )
370
+ val tpeOfRemainingGenerics =
371
+ typeArgs.zipWithIndex.filterNot(x => newSymToGenIndices(newFun.symbol).contains(x._2)).map(_._1)
372
+ assert(tpeOfRemainingGenerics.nonEmpty,
373
+ s " Remaining generics on ${newFun.symbol.name} not properly instantiated: missing types " )
362
374
Apply (TypeApply (newFun, tpeOfRemainingGenerics), args)
363
375
case _ =>
364
376
Apply (newFun, args)
0 commit comments