Skip to content

Commit 9718536

Browse files
committed
Update type_ordering.rs
* exclude ordering of nested unions (which cannot exist in DNF) as unreachable codes * try to avoid performance degradation in ordering of intersections
1 parent a089eb9 commit 9718536

File tree

2 files changed

+20
-25
lines changed

2 files changed

+20
-25
lines changed

crates/red_knot_python_semantic/src/types.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use ruff_db::files::File;
99
use ruff_python_ast as ast;
1010
use ruff_python_ast::name::Name;
1111
use ruff_text_size::{Ranged, TextRange};
12-
use type_ordering::union_elements_ordering;
12+
use type_ordering::union_or_intersection_elements_ordering;
1313

1414
pub(crate) use self::builder::{IntersectionBuilder, UnionBuilder};
1515
pub(crate) use self::diagnostic::register_lints;
@@ -5387,7 +5387,7 @@ impl<'db> UnionType<'db> {
53875387
.iter()
53885388
.map(|element| element.with_sorted_unions(db))
53895389
.collect();
5390-
new_elements.sort_unstable_by(|l, r| union_elements_ordering(l, r, db));
5390+
new_elements.sort_unstable_by(|l, r| union_or_intersection_elements_ordering(l, r, db));
53915391
UnionType::new(db, new_elements.into_boxed_slice())
53925392
}
53935393

@@ -5501,7 +5501,7 @@ impl<'db> IntersectionType<'db> {
55015501
.map(|ty| ty.with_sorted_unions(db))
55025502
.collect();
55035503

5504-
elements.sort_unstable_by(|l, r| union_elements_ordering(l, r, db));
5504+
elements.sort_unstable_by(|l, r| union_or_intersection_elements_ordering(l, r, db));
55055505
elements
55065506
}
55075507

crates/red_knot_python_semantic/src/types/type_ordering.rs

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ use super::{
1111
/// in an [`crate::types::IntersectionType`] or a [`crate::types::UnionType`] in order for them
1212
/// to be compared for equivalence.
1313
///
14-
/// Two unions / intersections are compared lexicographically.
14+
/// Two intersections are compared lexicographically.
15+
/// Two unions are never compared in this function because DNF does not permit nested unions.
1516
///
1617
/// Element types must already be sorted.
1718
///
@@ -21,7 +22,7 @@ use super::{
2122
/// create here is not user-facing. However, it doesn't really "make sense" for `Type` to implement
2223
/// [`Ord`] in terms of the semantics. There are many different ways in which you could plausibly
2324
/// sort a list of types; this is only one (somewhat arbitrary, at times) possible ordering.
24-
pub(super) fn union_elements_ordering<'db>(
25+
pub(super) fn union_or_intersection_elements_ordering<'db>(
2526
left: &Type<'db>,
2627
right: &Type<'db>,
2728
db: &'db dyn crate::Db,
@@ -269,38 +270,32 @@ pub(super) fn union_elements_ordering<'db>(
269270
(Type::Dynamic(_), _) => Ordering::Less,
270271
(_, Type::Dynamic(_)) => Ordering::Greater,
271272

272-
(Type::Union(left), Type::Union(right)) => {
273-
if left.elements(db).len() != right.elements(db).len() {
274-
return left.elements(db).len().cmp(&right.elements(db).len());
275-
}
276-
// Lexicographically compare the elements of the two unions.
277-
for (left, right) in left.elements(db).iter().zip(right.elements(db)) {
278-
let ordering = union_elements_ordering(left, right, db);
279-
if ordering != Ordering::Equal {
280-
return ordering;
281-
}
282-
}
283-
Ordering::Equal
273+
(Type::Union(_), Type::Union(_)) => {
274+
unreachable!("our type representation does not permit nested unions");
284275
}
285276
(Type::Union(_), _) => Ordering::Less,
286277
(_, Type::Union(_)) => Ordering::Greater,
287278

288279
(Type::Intersection(left), Type::Intersection(right)) => {
289280
// Lexicographically compare the elements of the two intersections.
290-
if left.positive(db).len() != right.positive(db).len() {
291-
return left.positive(db).len().cmp(&right.positive(db).len());
281+
let left_positive = left.positive(db);
282+
let right_positive = right.positive(db);
283+
if left_positive.len() != right_positive.len() {
284+
return left_positive.len().cmp(&right_positive.len());
292285
}
293-
if left.negative(db).len() != right.negative(db).len() {
294-
return left.negative(db).len().cmp(&right.negative(db).len());
286+
let left_negative = left.negative(db);
287+
let right_negative = right.negative(db);
288+
if left_negative.len() != right_negative.len() {
289+
return left_negative.len().cmp(&right_negative.len());
295290
}
296-
for (left, right) in left.positive(db).iter().zip(right.positive(db)) {
297-
let ordering = union_elements_ordering(left, right, db);
291+
for (left, right) in left_positive.iter().zip(right_positive) {
292+
let ordering = union_or_intersection_elements_ordering(left, right, db);
298293
if ordering != Ordering::Equal {
299294
return ordering;
300295
}
301296
}
302-
for (left, right) in left.negative(db).iter().zip(right.negative(db)) {
303-
let ordering = union_elements_ordering(left, right, db);
297+
for (left, right) in left_negative.iter().zip(right_negative) {
298+
let ordering = union_or_intersection_elements_ordering(left, right, db);
304299
if ordering != Ordering::Equal {
305300
return ordering;
306301
}

0 commit comments

Comments
 (0)