@@ -85,9 +85,9 @@ trait ConstraintHandling {
85
85
*/
86
86
protected def approximateWildcards : Boolean = true
87
87
88
- protected def addOneBound (param : TypeParamRef , bound0 : Type , isUpper : Boolean )(using Context ): Boolean =
88
+ protected def addOneBound (param : TypeParamRef , rawBound : Type , isUpper : Boolean )(using Context ): Boolean =
89
89
if ! constraint.contains(param) then true
90
- else if ! isUpper && param.occursIn(bound0 ) then
90
+ else if ! isUpper && param.occursIn(rawBound ) then
91
91
// We don't allow recursive lower bounds when defining a type,
92
92
// so we shouldn't allow them as constraints either.
93
93
false
@@ -100,16 +100,16 @@ trait ConstraintHandling {
100
100
val bounds = t.effectiveBounds
101
101
range(bounds.lo, bounds.hi)
102
102
else
103
- newTypeVar(t.effectiveBounds)
103
+ newTypeVar(apply( t.effectiveBounds).toBounds )
104
104
case _ =>
105
105
mapOver(t)
106
- val bound1 = dropWildcards(bound0 )
106
+ val bound = dropWildcards(rawBound )
107
107
val oldBounds @ TypeBounds (lo, hi) = constraint.nonParamBounds(param)
108
- val equalBounds = (if isUpper then lo else hi) eq bound1
109
- if equalBounds && ! bound1 .existsPart(_ eq param, stopAtStatic = true ) then
108
+ val equalBounds = (if isUpper then lo else hi) eq bound
109
+ if equalBounds && ! bound .existsPart(_ eq param, stopAtStatic = true ) then
110
110
// The narrowed bounds are equal and not recursive,
111
111
// so we can remove `param` from the constraint.
112
- constraint = constraint.replace(param, bound1 )
112
+ constraint = constraint.replace(param, bound )
113
113
true
114
114
else
115
115
// Narrow one of the bounds of type parameter `param`
@@ -119,8 +119,8 @@ trait ConstraintHandling {
119
119
val saved = homogenizeArgs
120
120
homogenizeArgs = Config .alignArgsInAnd
121
121
try
122
- if isUpper then oldBounds.derivedTypeBounds(lo, hi & bound1 )
123
- else oldBounds.derivedTypeBounds(lo | bound1 , hi)
122
+ if isUpper then oldBounds.derivedTypeBounds(lo, hi & bound )
123
+ else oldBounds.derivedTypeBounds(lo | bound , hi)
124
124
finally homogenizeArgs = saved
125
125
val c1 = constraint.updateEntry(param, narrowedBounds)
126
126
(c1 eq constraint)
@@ -260,83 +260,11 @@ trait ConstraintHandling {
260
260
* @pre `param` is in the constraint's domain.
261
261
*/
262
262
final def approximation (param : TypeParamRef , fromBelow : Boolean )(using Context ): Type =
263
-
264
- /** Substitute wildcards with fresh TypeParamRefs, to be compared with
265
- * other bound, so that they can be instantiated.
266
- */
267
- object substWildcards extends TypeMap :
268
- override def stopAtStatic = true
269
-
270
- var trackedPolis : List [PolyType ] = Nil
271
- def apply (tp : Type ) = tp match
272
- case tp : WildcardType =>
273
- assert(false )
274
- val poly = PolyType (tpnme.EMPTY :: Nil )(pt => tp.bounds :: Nil , pt => defn.AnyType )
275
- trackedPolis = poly :: trackedPolis
276
- poly.paramRefs.head
277
- case _ =>
278
- mapOver(tp)
279
- end substWildcards
280
-
281
- /** Replace TypeParamRefs substituted for wildcards by `substWildCards`
282
- * and any remaining wildcards by a safe approximation
283
- */
284
- val replaceWildcards = new TypeMap :
285
- override def stopAtStatic = true
286
-
287
- /** Try to instantiate a wildcard or TypeParamRef representing a wildcard
288
- * to a type that is known to conform to it.
289
- * This means:
290
- * If fromBelow is true, we minimize the type overall
291
- * Hence, if variance < 0, pick the maximal safe type: bounds.lo
292
- * (i.e. the whole bounds range is over the type).
293
- * If variance > 0, pick the minimal safe type: bounds.hi
294
- * (i.e. the whole bounds range is under the type).
295
- * If variance == 0, pick bounds.lo anyway (this is arbitrary but in line with
296
- * the principle that we pick the smaller type when in doubt).
297
- * If fromBelow is false, we maximize the type overall and reverse the bounds
298
- * If variance != 0. For variance == 0, we still minimize.
299
- * In summary we pick the bound given by this table:
300
- *
301
- * variance | -1 0 1
302
- * ------------------------
303
- * from below | lo lo hi
304
- * from above | hi lo lo
305
- */
306
- def pickOneBound (bounds : TypeBounds ) =
307
- if variance == 0 || fromBelow == (variance < 0 ) then bounds.lo
308
- else bounds.hi
309
-
310
- def apply (tp : Type ) = mapOver {
311
- tp match
312
- case tp : WildcardType =>
313
- assert(false )
314
- pickOneBound(tp.bounds)
315
- case tp : TypeParamRef if substWildcards.trackedPolis.contains(tp.binder) =>
316
- pickOneBound(fullBounds(tp))
317
- case _ => tp
318
- }
319
- end replaceWildcards
320
-
321
263
constraint.entry(param) match
322
264
case entry : TypeBounds =>
323
265
val useLowerBound = fromBelow || param.occursIn(entry.hi)
324
- val rawBound = if useLowerBound then fullLowerBound(param) else fullUpperBound(param)
325
- val bound = substWildcards(rawBound)
326
- val inst =
327
- if bound eq rawBound then bound
328
- else
329
- // Get rid of wildcards by mapping them to fresh TypeParamRefs
330
- // with constraints derived from comparing both bounds, and then
331
- // instantiating. See pos/i10161.scala for a test where this matters.
332
- val saved = constraint
333
- try
334
- for poly <- substWildcards.trackedPolis do addToConstraint(poly, Nil )
335
- if useLowerBound then bound <:< fullUpperBound(param)
336
- else fullLowerBound(param) <:< bound
337
- replaceWildcards(bound)
338
- finally constraint = saved
339
- typr.println(s " approx ${param.show}, from below = $fromBelow, bound = ${bound.show}, inst = ${inst.show}" )
266
+ val inst = if useLowerBound then fullLowerBound(param) else fullUpperBound(param)
267
+ typr.println(s " approx ${param.show}, from below = $fromBelow, inst = ${inst.show}" )
340
268
inst
341
269
case inst =>
342
270
assert(inst.exists, i " param = $param\n constraint = $constraint" )
0 commit comments