Skip to content

Commit c1f77a5

Browse files
committed
Fix regression in cyclic constraint handling
This regressed in 50eb0e9 when `current.ensureNonCyclic` was incorrectly replaced by `validBoundsFor` which operates on `this`, not `current`. This isn't the first time we make this error (cf a8641c5), maybe we should refactor OrderingConstraint so that operations on `current` are done in the companion object where `this` isn't accessible. Fixes #16471. Note that the test case from this issue couldn't be added because it fails `-Ycheck:typer`, but this was also the case before the regression. This is now tracked by #16524.
1 parent 5929a50 commit c1f77a5

File tree

2 files changed

+15
-1
lines changed

2 files changed

+15
-1
lines changed

compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
693693
def replaceParamIn(other: TypeParamRef) =
694694
val oldEntry = current.entry(other)
695695
val newEntry = oldEntry.substParam(param, replacement) match
696-
case tp: TypeBounds => validBoundsFor(other, tp)
696+
case tp: TypeBounds => current.validBoundsFor(other, tp)
697697
case tp => tp
698698
current = boundsLens.update(this, current, other, newEntry)
699699
var oldDepEntry = oldEntry

compiler/test/dotty/tools/dotc/core/ConstraintsTest.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,17 @@ class ConstraintsTest:
7777
assert(lo =:= defn.NothingType, i"Unexpected lower bound $lo for $t: ${ctx.typerState.constraint}")
7878
assert(hi =:= (defn.StringType | defn.IntType), i"Unexpected upper bound $hi for $t: ${ctx.typerState.constraint}")
7979
}
80+
81+
@Test def validBoundsReplace: Unit = inCompilerContext(
82+
TestConfiguration.basicClasspath,
83+
scalaSources = "trait X; trait A { def foo[S <: U | X, T, U]: Any }") {
84+
val tvarTrees = constrained(requiredClass("A").typeRef.select("foo".toTermName).info.asInstanceOf[TypeLambda], EmptyTree, alwaysAddTypeVars = true)._2
85+
val tvars @ List(s, t, u) = tvarTrees.tpes.asInstanceOf[List[TypeVar]]
86+
s =:= t
87+
t =:= u
88+
89+
for tvar <- tvars do
90+
val entry = ctx.typerState.constraint.entry(tvar.origin)
91+
assert(!ctx.typerState.constraint.occursAtToplevel(tvar.origin, entry),
92+
i"cyclic bound for ${tvar.origin}: ${entry} in ${ctx.typerState.constraint}")
93+
}

0 commit comments

Comments
 (0)