@@ -85,9 +85,9 @@ trait ConstraintHandling {
8585 */
8686 protected def approximateWildcards : Boolean = true
8787
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 =
8989 if ! constraint.contains(param) then true
90- else if ! isUpper && param.occursIn(bound0 ) then
90+ else if ! isUpper && param.occursIn(rawBound ) then
9191 // We don't allow recursive lower bounds when defining a type,
9292 // so we shouldn't allow them as constraints either.
9393 false
@@ -100,16 +100,16 @@ trait ConstraintHandling {
100100 val bounds = t.effectiveBounds
101101 range(bounds.lo, bounds.hi)
102102 else
103- newTypeVar(t.effectiveBounds)
103+ newTypeVar(apply( t.effectiveBounds).toBounds )
104104 case _ =>
105105 mapOver(t)
106- val bound1 = dropWildcards(bound0 )
106+ val bound = dropWildcards(rawBound )
107107 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
110110 // The narrowed bounds are equal and not recursive,
111111 // so we can remove `param` from the constraint.
112- constraint = constraint.replace(param, bound1 )
112+ constraint = constraint.replace(param, bound )
113113 true
114114 else
115115 // Narrow one of the bounds of type parameter `param`
@@ -119,8 +119,8 @@ trait ConstraintHandling {
119119 val saved = homogenizeArgs
120120 homogenizeArgs = Config .alignArgsInAnd
121121 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)
124124 finally homogenizeArgs = saved
125125 val c1 = constraint.updateEntry(param, narrowedBounds)
126126 (c1 eq constraint)
@@ -260,83 +260,11 @@ trait ConstraintHandling {
260260 * @pre `param` is in the constraint's domain.
261261 */
262262 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-
321263 constraint.entry(param) match
322264 case entry : TypeBounds =>
323265 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}" )
340268 inst
341269 case inst =>
342270 assert(inst.exists, i " param = $param\n constraint = $constraint" )
0 commit comments