Too severe precondition for slice::sort_by?

โš“ rust    ๐Ÿ“… 2025-07-16    ๐Ÿ‘ค surdeus    ๐Ÿ‘๏ธ 1      

surdeus

I have the strong impression that the function sort_by is not as useful as it seems, due
to the restriction on the compare parameter. The documentation of the function says:

May panic if compare does not implement a total order

I would like to have a guarantee that the following program will not panic.

use std::cmp::Ordering;

#[derive(Debug,PartialEq, Eq)]
struct Person {
    id: usize,
    age: i8,
}

impl Person {
    fn new(id: usize, age: i8) -> Person {
        Person{id, age}
    }
    fn cmp_by_age(p1: &Person, p2: &Person) -> Ordering {
        p1.age.cmp(&p2.age)
    }
}

fn main() {
    let mut persons=vec![Person::new(1,97), Person::new(2,15), Person::new(3,97)];
    persons.sort_by(Person::cmp_by_age);
    println!("persons sorted by age: {:?}", persons);
    assert!(persons[1] != persons[2]);
    assert_eq!(Person::cmp_by_age(&persons[1], &persons[2]), Ordering::Equal);
}

If I run this program, the output is as hoped for:

persons sorted by age: [Person { id: 2, age: 15 }, Person { id: 1, age: 97 }, Person { id: 3, age: 97 }]

But, could this program panic just as well? It looks like the answer is yes.
The documentation of the function states :โ€For more information and examples see the Ord documentation.โ€ Now, Ord is a trait of a type, not of some function or closure. So, we need to interpret.

The documentation states that the implementation of Ord must be consistent with PartialOrd. In particular:

partial_cmp(a, b) == Some(cmp(a, b))

The documentation of PartialOrd states that, amongst others, the following condition must hold:

a == b if and only if partial_cmp(a, b) == Some(Equal)

Filling in the consistency requirement, we get:

a == b if and only if Some(cmp(a, b)) == Some(Equal)

If we remove the Some on both sides:

a == b if and only if cmp(a, b) == Equal

If we fill in cmp_by_age for cmp, this condition is not met, as we can see from the two assertions in the code.

My questions:

  • Is my conclusion correct that I cannot use sort_by confidently in cases as above?
  • If so, why doesnโ€™t the Rust standard library sort the way C++ does? That is, require a weak ordering instead of a total ordering.

2 posts - 2 participants

Read full topic

๐Ÿท๏ธ rust_feed