@@ -113,7 +113,8 @@ import OrderingConstraint._
113
113
* polytype's type parameters. The second half might contain type variables that
114
114
* track the corresponding parameters, or is left empty (filled with nulls).
115
115
* An instantiated type parameter is represented by having its instance type in
116
- * the corresponding array entry.
116
+ * the corresponding array entry. The dual use of arrays for poly params
117
+ * and typevars is to save space and hopefully gain some speed.
117
118
*
118
119
* @param lowerMap a map from PolyTypes to arrays. Each array entry corresponds
119
120
* to a parameter P of the polytype; it contains all constrained parameters
@@ -212,9 +213,46 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
212
213
213
214
// ---------- Adding PolyTypes --------------------------------------------------
214
215
215
- /** The bound type `tp` without dependent parameters
216
- * NoType if type consists only of dependent parameters.
217
- * @param seenFromBelow If true, `bound` is an upper bound, else a lower bound.
216
+ /** The list of parameters P such that, for a fresh type parameter Q:
217
+ *
218
+ * Q <: tp implies Q <: P and isUpper = true, or
219
+ * tp <: Q implies P <: Q and isUpper = false
220
+ */
221
+ def dependentParams (tp : Type , isUpper : Boolean ): List [PolyParam ] = tp match {
222
+ case param : PolyParam if contains(param) =>
223
+ param :: (if (isUpper) upper(param) else lower(param))
224
+ case tp : AndOrType =>
225
+ val ps1 = dependentParams(tp.tp1, isUpper)
226
+ val ps2 = dependentParams(tp.tp2, isUpper)
227
+ if (isUpper == tp.isAnd) ps1.union(ps2) else ps1.intersect(ps2)
228
+ case _ =>
229
+ Nil
230
+ }
231
+
232
+ /** The bound type `tp` without constrained parameters which are clearly
233
+ * dependent. A parameter in an upper bound is clearly dependent if it appears
234
+ * in a hole of a context H given by:
235
+ *
236
+ * H = []
237
+ * H & T
238
+ * T & H
239
+ *
240
+ * (the idea is that a parameter P in a H context is guaranteed to be a supertype of the
241
+ * bounded parameter.)
242
+ * Analogously, a parameter in a lower bound is clearly dependent if it appears
243
+ * in a hole of a context H given by:
244
+ *
245
+ * L = []
246
+ * L | T
247
+ * T | L
248
+ *
249
+ * "Clearly dependent" is not synonymous with "dependent" in the sense
250
+ * it is defined in `dependentParams`. Dependent parameters are handled
251
+ * in `updateEntry`. The idea of stripping off clearly dependent parameters
252
+ * and to handle them separately is for efficiency, so that type expressions
253
+ * used as bounds become smaller.
254
+ *
255
+ * @param isUpper If true, `bound` is an upper bound, else a lower bound.
218
256
*/
219
257
private def stripParams (tp : Type , paramBuf : mutable.ListBuffer [PolyParam ],
220
258
isUpper : Boolean )(implicit ctx : Context ): Type = tp match {
@@ -232,9 +270,9 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
232
270
tp
233
271
}
234
272
235
- /** The bound type `tp` without dependent parameters.
273
+ /** The bound type `tp` without clearly dependent parameters.
236
274
* A top or bottom type if type consists only of dependent parameters.
237
- * @param seenFromBelow If true, `bound` is an upper bound, else a lower bound.
275
+ * @param isUpper If true, `bound` is an upper bound, else a lower bound.
238
276
*/
239
277
private def normalizedType (tp : Type , paramBuf : mutable.ListBuffer [PolyParam ],
240
278
isUpper : Boolean )(implicit ctx : Context ): Type =
@@ -259,7 +297,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
259
297
val bounds = nonParamBounds(param)
260
298
val lo = normalizedType(bounds.lo, loBuf, isUpper = false )
261
299
val hi = normalizedType(bounds.hi, hiBuf, isUpper = true )
262
- current = boundsLens.update( this , current, poly, i , bounds.derivedTypeBounds(lo, hi))
300
+ current = updateEntry( current, param , bounds.derivedTypeBounds(lo, hi))
263
301
current = (current /: loBuf)(order(_, _, param))
264
302
current = (current /: hiBuf)(order(_, param, _))
265
303
loBuf.clear()
@@ -289,9 +327,22 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
289
327
290
328
def addLess (param1 : PolyParam , param2 : PolyParam )(implicit ctx : Context ): This =
291
329
order(this , param1, param2)
330
+
331
+ def updateEntry (current : This , param : PolyParam , tp : Type )(implicit ctx : Context ): This = {
332
+ var current1 = boundsLens.update(this , current, param, tp)
333
+ tp match {
334
+ case TypeBounds (lo, hi) =>
335
+ for (p <- dependentParams(lo, isUpper = false ))
336
+ current1 = order(current1, p, param)
337
+ for (p <- dependentParams(hi, isUpper = true ))
338
+ current1 = order(current1, param, p)
339
+ case _ =>
340
+ }
341
+ current1
342
+ }
292
343
293
344
def updateEntry (param : PolyParam , tp : Type )(implicit ctx : Context ): This =
294
- boundsLens.update( this , this , param, tp)
345
+ updateEntry( this , param, tp)
295
346
296
347
def unify (p1 : PolyParam , p2 : PolyParam )(implicit ctx : Context ): This = {
297
348
val p1Bounds = (nonParamBounds(p1) & nonParamBounds(p2)).substParam(p2, p1)
0 commit comments