Skip to content

Commit 7a5f48a

Browse files
Backport "Retry constraint.replace after constraint.updateEntry" to LTS (#21111)
Backports #20399 to the LTS branch. PR submitted by the release tooling. [skip ci]
2 parents ffaab87 + e1aeea5 commit 7a5f48a

File tree

1 file changed

+33
-23
lines changed

1 file changed

+33
-23
lines changed

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

+33-23
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ trait ConstraintHandling {
112112
*/
113113
private var myTrustBounds = true
114114

115-
inline def withUntrustedBounds(op: => Type): Type =
115+
transparent inline def withUntrustedBounds(op: => Type): Type =
116116
val saved = myTrustBounds
117117
myTrustBounds = false
118118
try op finally myTrustBounds = saved
@@ -293,34 +293,44 @@ trait ConstraintHandling {
293293
// so we shouldn't allow them as constraints either.
294294
false
295295
else
296-
val bound = legalBound(param, rawBound, isUpper)
297-
val oldBounds @ TypeBounds(lo, hi) = constraint.nonParamBounds(param)
298-
val equalBounds = (if isUpper then lo else hi) eq bound
299-
if equalBounds && !bound.existsPart(_ eq param, StopAt.Static) then
300-
// The narrowed bounds are equal and not recursive,
301-
// so we can remove `param` from the constraint.
302-
constraint = constraint.replace(param, bound)
303-
true
304-
else
305-
// Narrow one of the bounds of type parameter `param`
306-
// If `isUpper` is true, ensure that `param <: `bound`, otherwise ensure
307-
// that `param >: bound`.
308-
val narrowedBounds =
309-
val saved = homogenizeArgs
310-
homogenizeArgs = Config.alignArgsInAnd
311-
try
312-
withUntrustedBounds(
313-
if isUpper then oldBounds.derivedTypeBounds(lo, hi & bound)
314-
else oldBounds.derivedTypeBounds(lo | bound, hi))
315-
finally
316-
homogenizeArgs = saved
296+
297+
// Narrow one of the bounds of type parameter `param`
298+
// If `isUpper` is true, ensure that `param <: `bound`,
299+
// otherwise ensure that `param >: bound`.
300+
val narrowedBounds: TypeBounds =
301+
val bound = legalBound(param, rawBound, isUpper)
302+
val oldBounds @ TypeBounds(lo, hi) = constraint.nonParamBounds(param)
303+
304+
val saved = homogenizeArgs
305+
homogenizeArgs = Config.alignArgsInAnd
306+
try
307+
withUntrustedBounds(
308+
if isUpper then oldBounds.derivedTypeBounds(lo, hi & bound)
309+
else oldBounds.derivedTypeBounds(lo | bound, hi))
310+
finally
311+
homogenizeArgs = saved
312+
end narrowedBounds
313+
314+
// If the narrowed bounds are equal and not recursive,
315+
// we can remove `param` from the constraint.
316+
def tryReplace(newBounds: TypeBounds): Boolean =
317+
val TypeBounds(lo, hi) = newBounds
318+
val canReplace = (lo eq hi) && !newBounds.existsPart(_ eq param, StopAt.Static)
319+
if canReplace then constraint = constraint.replace(param, lo)
320+
canReplace
321+
322+
tryReplace(narrowedBounds) || locally:
317323
//println(i"narrow bounds for $param from $oldBounds to $narrowedBounds")
318324
val c1 = constraint.updateEntry(param, narrowedBounds)
319325
(c1 eq constraint)
320326
|| {
321327
constraint = c1
322328
val TypeBounds(lo, hi) = constraint.entry(param): @unchecked
323-
isSub(lo, hi)
329+
val isSat = isSub(lo, hi)
330+
if isSat then
331+
// isSub may have narrowed the bounds further
332+
tryReplace(constraint.nonParamBounds(param))
333+
isSat
324334
}
325335
end addOneBound
326336

0 commit comments

Comments
 (0)