@@ -300,8 +300,8 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
300
300
// ---------- Updates ------------------------------------------------------------
301
301
302
302
/** If `inst` is a TypeBounds, make sure it does not contain toplevel
303
- * references to `param`. Toplevel means: the term itself or a factor in some
304
- * combination of `&` or `|` types .
303
+ * references to `param` (see `Constraint#occursAtToplevel` for a definition
304
+ * of "toplevel") .
305
305
* Any such references are replace by `Nothing` in the lower bound and `Any`
306
306
* in the upper bound.
307
307
* References can be direct or indirect through instantiations of other
@@ -594,33 +594,36 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
594
594
// ---------- Checking -----------------------------------------------
595
595
596
596
def checkNonCyclic ()(implicit ctx : Context ): this .type =
597
- if Config .checkConstraintsNonCyclic then domainParams.foreach(checkNonCyclic)
597
+ if Config .checkConstraintsNonCyclic then
598
+ domainParams.foreach { param =>
599
+ val inst = entry(param)
600
+ assert(! isLess(param, param),
601
+ s " cyclic ordering involving $param in ${this .show}, upper = $inst" )
602
+ assert(! occursAtToplevel(param, inst),
603
+ s " cyclic bound for $param: ${inst.show} in ${this .show}" )
604
+ }
598
605
this
599
606
600
- private def checkNonCyclic (param : TypeParamRef )(implicit ctx : Context ): Unit =
601
- assert(! isLess(param, param), i " cyclic ordering involving $param in $this, upper = ${upper(param)}" )
607
+ def occursAtToplevel (param : TypeParamRef , inst : Type )(implicit ctx : Context ): Boolean =
602
608
603
- def recur (tp : Type )(using Context ): Unit = tp match
609
+ def occurs (tp : Type )(using Context ): Boolean = tp match
604
610
case tp : AndOrType =>
605
- recur(tp.tp1)
606
- recur(tp.tp2)
611
+ occurs(tp.tp1) || occurs(tp.tp2)
607
612
case tp : TypeParamRef =>
608
- assert(tp ne param, i " cyclic bound for $param: ${entry(param)} in $this" )
609
- entry(tp) match
610
- case NoType =>
611
- case TypeBounds (lo, hi) => if lo eq hi then recur(lo)
612
- case inst => recur(inst)
613
+ (tp eq param) || entry(tp).match
614
+ case NoType => false
615
+ case TypeBounds (lo, hi) => (lo eq hi) && occurs(lo)
616
+ case inst => occurs(inst)
613
617
case tp : TypeVar =>
614
- recur (tp.underlying)
618
+ occurs (tp.underlying)
615
619
case TypeBounds (lo, hi) =>
616
- recur(lo)
617
- recur(hi)
620
+ occurs(lo) || occurs(hi)
618
621
case _ =>
619
622
val tp1 = tp.dealias
620
- if tp1 ne tp then recur (tp1)
623
+ ( tp1 ne tp) && occurs (tp1)
621
624
622
- recur(entry(param) )
623
- end checkNonCyclic
625
+ occurs(inst )
626
+ end occursAtToplevel
624
627
625
628
override def checkClosed ()(using Context ): Unit =
626
629
0 commit comments