Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[red-knot] Ensure differently ordered unions are considered equivalent when they appear inside tuples inside top-level intersections #15743

Merged
merged 1 commit into from
Jan 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,16 @@ static_assert(
)
```

## Intersections containing tuples containing unions

```py
from knot_extensions import is_equivalent_to, static_assert, Intersection

class P: ...
class Q: ...
class R: ...

static_assert(is_equivalent_to(Intersection[tuple[P | Q], R], Intersection[tuple[Q | P], R]))
```

[the equivalence relation]: https://typing.readthedocs.io/en/latest/spec/glossary.html#term-equivalent
26 changes: 22 additions & 4 deletions crates/red_knot_python_semantic/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4516,21 +4516,33 @@ impl<'db> IntersectionType<'db> {
}

let self_positive = self.positive(db);

if !all_fully_static(db, self_positive) {
return false;
}

let self_negative = self.negative(db);
if !all_fully_static(db, self_negative) {
let other_positive = other.positive(db);

if self_positive.len() != other_positive.len() {
return false;
}

let other_positive = other.positive(db);
if !all_fully_static(db, other_positive) {
return false;
}

let self_negative = self.negative(db);

if !all_fully_static(db, self_negative) {
return false;
}

let other_negative = other.negative(db);

if self_negative.len() != other_negative.len() {
return false;
}

if !all_fully_static(db, other_negative) {
return false;
}
Expand All @@ -4539,7 +4551,13 @@ impl<'db> IntersectionType<'db> {
return true;
}

self_positive.set_eq(other_positive) && self_negative.set_eq(other_negative)
let sorted_self = self.to_sorted_intersection(db);

if sorted_self == other {
return true;
}

sorted_self == other.to_sorted_intersection(db)
}

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