@@ -86,22 +86,25 @@ trait ConstraintHandling[AbstractContext] {
86
86
def fullBounds (param : TypeParamRef )(implicit actx : AbstractContext ): TypeBounds =
87
87
nonParamBounds(param).derivedTypeBounds(fullLowerBound(param), fullUpperBound(param))
88
88
89
- protected def addOneBound (param : TypeParamRef , bound : Type , isUpper : Boolean )(implicit actx : AbstractContext ): Boolean =
89
+ protected def addOneBound (param : TypeParamRef , rawBound : Type , isUpper : Boolean )(implicit actx : AbstractContext ): Boolean =
90
90
! constraint.contains(param) || {
91
- def occursIn (bound : Type ): Boolean = {
92
- val b = bound.dealias
93
- (b eq param) || {
94
- b match {
95
- case b : AndType => occursIn(b.tp1) || occursIn(b.tp2)
96
- case b : OrType => occursIn(b.tp1) || occursIn(b.tp2)
97
- case b : TypeVar => occursIn(b.origin)
98
- case b : TermRef => occursIn(b.underlying)
99
- case _ => false
100
- }
101
- }
102
- }
103
- if (Config .checkConstraintsSeparated)
104
- assert(! occursIn(bound), s " $param occurs in $bound" )
91
+ def avoidCycle (tp : Type ): Type = tp match
92
+ case tp : AndOrType =>
93
+ tp.derivedAndOrType(avoidCycle(tp.tp1), avoidCycle(tp.tp2))
94
+ case tp : TypeParamRef =>
95
+ if tp eq param then
96
+ // println(i"stripping $tp from $rawBound, upper = $isUpper in $constraint")
97
+ if isUpper then fullLowerBound(tp)
98
+ else fullUpperBound(tp)
99
+ else constraint.entry(tp) match
100
+ case TypeBounds (lo, hi) => if lo eq hi then avoidCycle(lo) else tp
101
+ case inst => avoidCycle(inst)
102
+ case tp : TypeVar =>
103
+ val underlying1 = avoidCycle(tp.underlying)
104
+ if underlying1 eq tp.underlying then tp else underlying1
105
+ case _ =>
106
+ tp
107
+ val bound = avoidCycle(rawBound)
105
108
106
109
val oldBounds @ TypeBounds (lo, hi) = constraint.nonParamBounds(param)
107
110
val equalBounds = isUpper && (lo eq bound) || ! isUpper && (bound eq hi)
@@ -275,6 +278,9 @@ trait ConstraintHandling[AbstractContext] {
275
278
// from above | hi lo lo
276
279
//
277
280
if (variance == 0 || fromBelow == (variance < 0 )) bounds.lo else bounds.hi
281
+ case `param` =>
282
+ if variance == 0 || fromBelow == (variance < 0 ) then defn.AnyType
283
+ else defn.NothingType
278
284
case _ => tp
279
285
}
280
286
}
@@ -483,7 +489,7 @@ trait ConstraintHandling[AbstractContext] {
483
489
if bnd eq param then // (1)
484
490
if fromBelow then defn.NothingType else defn.AnyType
485
491
else constraint.entry(bnd) match
486
- case _ : TypeBounds => bnd
492
+ case TypeBounds (lo, hi) => if lo eq hi then prune(lo) else bnd
487
493
case inst => prune(inst) // (3)
488
494
case bnd : ExprType => // (4)
489
495
// ExprTypes are not value types, so type parameters should not
0 commit comments