@@ -229,23 +229,32 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
229
229
* and to handle them separately is for efficiency, so that type expressions
230
230
* used as bounds become smaller.
231
231
*
232
+ * TODO: try to do without stripping? It would mean it is more efficient
233
+ * to pull out full bounds from a constraint.
234
+ *
232
235
* @param isUpper If true, `bound` is an upper bound, else a lower bound.
233
236
*/
234
- private def stripParams (tp : Type , paramBuf : mutable.ListBuffer [TypeParamRef ],
237
+ private def stripParams (
238
+ tp : Type ,
239
+ todos : mutable.ListBuffer [(OrderingConstraint , TypeParamRef ) => OrderingConstraint ],
235
240
isUpper : Boolean )(using Context ): Type = tp match {
236
241
case param : TypeParamRef if contains(param) =>
237
- if ( ! paramBuf.contains( param)) paramBuf += param
242
+ todos += ( if isUpper then order(_, _, param) else order(_, param, _))
238
243
NoType
244
+ case tp : TypeBounds =>
245
+ val lo1 = stripParams(tp.lo, todos, ! isUpper).orElse(defn.NothingType )
246
+ val hi1 = stripParams(tp.hi, todos, isUpper).orElse(defn.AnyKindType )
247
+ tp.derivedTypeBounds(lo1, hi1)
239
248
case tp : AndType if isUpper =>
240
- val tp1 = stripParams(tp.tp1, paramBuf , isUpper)
241
- val tp2 = stripParams(tp.tp2, paramBuf , isUpper)
249
+ val tp1 = stripParams(tp.tp1, todos , isUpper)
250
+ val tp2 = stripParams(tp.tp2, todos , isUpper)
242
251
if (tp1.exists)
243
252
if (tp2.exists) tp.derivedAndType(tp1, tp2)
244
253
else tp1
245
254
else tp2
246
255
case tp : OrType if ! isUpper =>
247
- val tp1 = stripParams(tp.tp1, paramBuf , isUpper)
248
- val tp2 = stripParams(tp.tp2, paramBuf , isUpper)
256
+ val tp1 = stripParams(tp.tp1, todos , isUpper)
257
+ val tp2 = stripParams(tp.tp2, todos , isUpper)
249
258
if (tp1.exists)
250
259
if (tp2.exists) tp.derivedOrType(tp1, tp2)
251
260
else tp1
@@ -254,17 +263,6 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
254
263
tp
255
264
}
256
265
257
- /** The bound type `tp` without clearly dependent parameters.
258
- * A top or bottom type if type consists only of dependent parameters.
259
- * TODO: try to do without normalization? It would mean it is more efficient
260
- * to pull out full bounds from a constraint.
261
- * @param isUpper If true, `bound` is an upper bound, else a lower bound.
262
- */
263
- private def normalizedType (tp : Type , paramBuf : mutable.ListBuffer [TypeParamRef ],
264
- isUpper : Boolean )(using Context ): Type =
265
- stripParams(tp, paramBuf, isUpper)
266
- .orElse(if (isUpper) defn.AnyKindType else defn.NothingType )
267
-
268
266
def add (poly : TypeLambda , tvars : List [TypeVar ])(using Context ): This = {
269
267
assert(! contains(poly))
270
268
val nparams = poly.paramNames.length
@@ -280,18 +278,15 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
280
278
*/
281
279
private def init (poly : TypeLambda )(using Context ): This = {
282
280
var current = this
283
- val loBuf, hiBuf = new mutable.ListBuffer [TypeParamRef ]
281
+ val todos = new mutable.ListBuffer [( OrderingConstraint , TypeParamRef ) => OrderingConstraint ]
284
282
var i = 0
285
283
while (i < poly.paramNames.length) {
286
284
val param = poly.paramRefs(i)
287
- val bounds = nonParamBounds(param)
288
- val lo = normalizedType(bounds.lo, loBuf, isUpper = false )
289
- val hi = normalizedType(bounds.hi, hiBuf, isUpper = true )
290
- current = updateEntry(current, param, bounds.derivedTypeBounds(lo, hi))
291
- current = loBuf.foldLeft(current)(order(_, _, param))
292
- current = hiBuf.foldLeft(current)(order(_, param, _))
293
- loBuf.clear()
294
- hiBuf.clear()
285
+ val stripped = stripParams(nonParamBounds(param), todos, isUpper = true )
286
+ current = updateEntry(current, param, stripped)
287
+ while todos.nonEmpty do
288
+ current = todos.head(current, param)
289
+ todos.dropInPlace(1 )
295
290
i += 1
296
291
}
297
292
current.checkNonCyclic()
0 commit comments