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
Fix spurious subtype check pruning when both sides have unions (#18213)
Fixes#17465.
In TypeComparer, `fourthTry` calls `isNewSubType` and `isCovered` to
detect the subtype queries that have been covered by previous attempts
and prune them. However, the pruning is spurious when both sides contain
union types, as exemplified by the following subtype trace before the
PR:
```
==> isSubType (test1 : (Int | String){def foo(x: Int): Int}) <:< Int | String?
==> isSubType (Int | String){def foo(x: Int): Int} <:< Int | String?
==> isSubType (Int | String){def foo(x: Int): Int} <:< Int?
<== isSubType (Int | String){def foo(x: Int): Int} <:< Int = false
==> isSubType (Int | String){def foo(x: Int): Int} <:< String?
==> isSubType (Int | String){def foo(x: Int): Int} <:< String?
<== isSubType (Int | String){def foo(x: Int): Int} <:< String = false
<== isSubType (Int | String){def foo(x: Int): Int} <:< String = false
// (1): follow-up subtype checks are pruned here by isNewSubType
<== isSubType (Int | String){def foo(x: Int): Int} <:< Int | String = false
<== isSubType (test1 : (Int | String){def foo(x: Int): Int}) <:< Int | String = false
```
At `(1)`, the pruning condition is met, and follow-up recursions are
skipped. However, in this case, only after `(1)` are the refinement on
LHS dropped and the subtype between two identical OrTypes are accepted.
The pruning is spurious.
This PR tempers the pruning conditions specified in `isCovered` and
`isNewSubType` to fix these false negatives.
0 commit comments