Skip to content

Commit c824140

Browse files
authored
[red-knot] Ensure differently ordered unions are considered equivalent when they appear inside tuples inside top-level intersections (#15743)
1 parent f85ea1b commit c824140

File tree

2 files changed

+34
-4
lines changed

2 files changed

+34
-4
lines changed

crates/red_knot_python_semantic/resources/mdtest/type_properties/is_equivalent_to.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,16 @@ static_assert(
106106
)
107107
```
108108

109+
## Intersections containing tuples containing unions
110+
111+
```py
112+
from knot_extensions import is_equivalent_to, static_assert, Intersection
113+
114+
class P: ...
115+
class Q: ...
116+
class R: ...
117+
118+
static_assert(is_equivalent_to(Intersection[tuple[P | Q], R], Intersection[tuple[Q | P], R]))
119+
```
120+
109121
[the equivalence relation]: https://typing.readthedocs.io/en/latest/spec/glossary.html#term-equivalent

crates/red_knot_python_semantic/src/types.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4516,21 +4516,33 @@ impl<'db> IntersectionType<'db> {
45164516
}
45174517

45184518
let self_positive = self.positive(db);
4519+
45194520
if !all_fully_static(db, self_positive) {
45204521
return false;
45214522
}
45224523

4523-
let self_negative = self.negative(db);
4524-
if !all_fully_static(db, self_negative) {
4524+
let other_positive = other.positive(db);
4525+
4526+
if self_positive.len() != other_positive.len() {
45254527
return false;
45264528
}
45274529

4528-
let other_positive = other.positive(db);
45294530
if !all_fully_static(db, other_positive) {
45304531
return false;
45314532
}
45324533

4534+
let self_negative = self.negative(db);
4535+
4536+
if !all_fully_static(db, self_negative) {
4537+
return false;
4538+
}
4539+
45334540
let other_negative = other.negative(db);
4541+
4542+
if self_negative.len() != other_negative.len() {
4543+
return false;
4544+
}
4545+
45344546
if !all_fully_static(db, other_negative) {
45354547
return false;
45364548
}
@@ -4539,7 +4551,13 @@ impl<'db> IntersectionType<'db> {
45394551
return true;
45404552
}
45414553

4542-
self_positive.set_eq(other_positive) && self_negative.set_eq(other_negative)
4554+
let sorted_self = self.to_sorted_intersection(db);
4555+
4556+
if sorted_self == other {
4557+
return true;
4558+
}
4559+
4560+
sorted_self == other.to_sorted_intersection(db)
45434561
}
45444562

45454563
/// Return `true` if `self` has exactly the same set of possible static materializations as `other`

0 commit comments

Comments
 (0)