diff --git a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala index 46c325209dee..ff3f5c4269dd 100644 --- a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala +++ b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala @@ -627,11 +627,7 @@ trait ConstraintHandling { case x => // Happens if param was already solved while processing earlier params of the same TypeLambda. // See #4720. - - // Should propagate bounds even when param has been solved. - // See #11682. - lower.forall(addOneBound(_, x, isUpper = true)) && - upper.forall(addOneBound(_, x, isUpper = false)) + true } } } @@ -677,6 +673,11 @@ trait ConstraintHandling { case t @ TypeParamRef(tl: TypeLambda, n) if comparedTypeLambdas contains tl => val bounds = tl.paramInfos(n) range(bounds.lo, bounds.hi) + case tl: TypeLambda => + val saved = comparedTypeLambdas + comparedTypeLambdas -= tl + try mapOver(tl) + finally comparedTypeLambdas = saved case _ => mapOver(t) } diff --git a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala index 6974f7f1b836..675816ad200f 100644 --- a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala +++ b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala @@ -354,13 +354,18 @@ class OrderingConstraint(private val boundsMap: ParamBounds, * `<:<` relationships between parameters ("edges") but not bounds. */ def order(current: This, param1: TypeParamRef, param2: TypeParamRef, direction: UnificationDirection = NoUnification)(using Context): This = - if (param1 == param2 || current.isLess(param1, param2)) this - else { - assert(contains(param1), i"$param1") - assert(contains(param2), i"$param2") + // /!\ Careful here: we're adding constraints on `current`, not `this`, so + // think twice when using an instance method! We only need to pass `this` as + // the `prev` argument in methods on `ConstraintLens`. + // TODO: Refactor this code to take `prev` as a parameter and add + // constraints on `this` instead? + if param1 == param2 || current.isLess(param1, param2) then current + else + assert(current.contains(param1), i"$param1") + assert(current.contains(param2), i"$param2") val unifying = direction != NoUnification val newUpper = { - val up = exclusiveUpper(param2, param1) + val up = current.exclusiveUpper(param2, param1) if unifying then // Since param2 <:< param1 already holds now, filter out param1 to avoid adding // duplicated orderings. @@ -374,7 +379,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, param2 :: up } val newLower = { - val lower = exclusiveLower(param1, param2) + val lower = current.exclusiveLower(param1, param2) if unifying then // Similarly, filter out param2 from lowerly-ordered parameters // to avoid duplicated orderings. @@ -390,7 +395,8 @@ class OrderingConstraint(private val boundsMap: ParamBounds, val current1 = newLower.foldLeft(current)(upperLens.map(this, _, _, newUpper ::: _)) val current2 = newUpper.foldLeft(current1)(lowerLens.map(this, _, _, newLower ::: _)) current2 - } + end if + end order /** The list of parameters P such that, for a fresh type parameter Q: *