@@ -295,11 +295,24 @@ trait ConstraintHandling {
295
295
end legalBound
296
296
297
297
protected def addOneBound (param : TypeParamRef , rawBound : Type , isUpper : Boolean )(using Context ): Boolean =
298
+
299
+ // Replace top-level occurrences of `param` in `bound` by `Nothing`
300
+ def sanitize (bound : Type ): Type =
301
+ if bound.stripped eq param then defn.NothingType
302
+ else bound match
303
+ case bound : AndOrType =>
304
+ bound.derivedAndOrType(sanitize(bound.tp1), sanitize(bound.tp2))
305
+ case _ =>
306
+ bound
307
+
298
308
if ! constraint.contains(param) then true
299
- else if ! isUpper && param.occursIn(rawBound) then
300
- // We don't allow recursive lower bounds when defining a type,
301
- // so we shouldn't allow them as constraints either.
302
- false
309
+ else if ! isUpper && param.occursIn(rawBound.widen) then
310
+ val rawBound1 = sanitize(rawBound.widenDealias)
311
+ if param.occursIn(rawBound1) then
312
+ // We don't allow recursive lower bounds when defining a type,
313
+ // so we shouldn't allow them as constraints either.
314
+ false
315
+ else addOneBound(param, rawBound1, isUpper)
303
316
else
304
317
305
318
// Narrow one of the bounds of type parameter `param`
@@ -730,6 +743,7 @@ trait ConstraintHandling {
730
743
// (we do not check for non-toplevel occurrences: those should never occur
731
744
// since `addOneBound` disallows recursive lower bounds).
732
745
if constraint.occursAtToplevel(param, widened) then
746
+ assert(widened ne approx, i " instance of $param = $approx in $constraint" )
733
747
instanceType(param, fromBelow, widen, maxLevel)
734
748
else
735
749
widened
0 commit comments