Skip to content

Commit 49940ee

Browse files
Retry constraint.replace after constraint.updateEntry
Checking `isSub` on the resulting bounds can have introduced new constraints, which might allow us to replace the type parameter entirely.
1 parent 4dffcc9 commit 49940ee

File tree

1 file changed

+14
-8
lines changed

1 file changed

+14
-8
lines changed

Diff for: compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala

+14-8
Original file line numberDiff line numberDiff line change
@@ -302,14 +302,18 @@ trait ConstraintHandling {
302302
false
303303
else
304304
val bound = legalBound(param, rawBound, isUpper)
305+
lazy val recBound = bound.existsPart(_ eq param, StopAt.Static)
306+
307+
// If the narrowed bounds are equal and not recursive,
308+
// we can remove `param` from the constraint.
309+
def tryReplace(lo: Type, hi: Type): Boolean =
310+
val equalBounds = (if isUpper then lo else hi) eq bound
311+
val canReplace = equalBounds && !recBound
312+
if canReplace then constraint = constraint.replace(param, bound)
313+
canReplace
314+
305315
val oldBounds @ TypeBounds(lo, hi) = constraint.nonParamBounds(param)
306-
val equalBounds = (if isUpper then lo else hi) eq bound
307-
if equalBounds && !bound.existsPart(_ eq param, StopAt.Static) then
308-
// The narrowed bounds are equal and not recursive,
309-
// so we can remove `param` from the constraint.
310-
constraint = constraint.replace(param, bound)
311-
true
312-
else
316+
tryReplace(lo, hi) || locally:
313317
// Narrow one of the bounds of type parameter `param`
314318
// If `isUpper` is true, ensure that `param <: `bound`, otherwise ensure
315319
// that `param >: bound`.
@@ -328,7 +332,9 @@ trait ConstraintHandling {
328332
|| {
329333
constraint = c1
330334
val TypeBounds(lo, hi) = constraint.entry(param): @unchecked
331-
isSub(lo, hi)
335+
val isSat = isSub(lo, hi)
336+
if isSat then tryReplace(lo, hi) // isSub may have introduced new constraints
337+
isSat
332338
}
333339
end addOneBound
334340

0 commit comments

Comments
 (0)