You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Avoid incorrect simplifications when updating bounds in the constraint
When combining an old and a new bound, we use `Type#&`/`Type#|` which perform
simplifications. This is usually fine, but if the new bounds refer to the
parameter currently being updated, we can run into cyclic reasoning issues which
make the simplifications invalid after the update.
We already have logic for handling self-references in parameter bounds:
`updateEntry` calls `ensureNonCyclic` which sanitizes the type, but at this point
the simplifications have already occured. This commit simply moves the logic out
of `updateEntry` so that we can sanitize the new bounds before simplification.
More precisely, we rename `ensureNonCyclic` to `validBoundsFor` which calls
`validBoundFor`. Both are used to sanitize bounds where needed in `addOneBound`
and `unify`.
Since all calls to `updateEntry` now have sanitized bounds, we no longer need to
sanitize them in `updateEntry` itself, we document this change by adding a
pre-condition to `updateEntry`.
For the record, here's how `ConstraintsTest#validBoundsInit` used to fail.
It defines a method:
def foo[S >: T <: T | Int, T <: String]: Any
Before this commit, when `foo` was added to the current constraints, the
constraint `S <: T | Int` was propagated to the lower bound `T` of `S`. The
updated upper bound of `T` was thus set to:
String & (T | Int)
But because `Type#&` performs simplifications, this became
T | (String & Int)
by relying on the fact that at this point, `T <: String`. But in fact this
simplified bound no longer ensures that `T <: String`! The self-reference was
then replaced by `Any` in `OrderingConstraint#ensureNonCyclic`.
After this commit, the problematic simplification no longer occurs since the
new `T | Int` is sanitized to `Any` before being intersected with the old bound.
0 commit comments