Skip to content
22 changes: 13 additions & 9 deletions library/alloc/src/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,21 +176,25 @@ pub(crate) mod hack {
impl<T> [T] {
/// Sorts the slice.
///
/// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*)) worst-case.
/// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*))
/// worst-case. Fully ascending or descending inputs are completed with O(n-1) comparisons.
///
/// When applicable, unstable sorting is preferred because it is generally faster than stable
/// sorting and it doesn't allocate auxiliary memory.
/// See [`sort_unstable`](slice::sort_unstable).
/// sorting and it doesn't allocate auxiliary memory. See
/// [`sort_unstable`](slice::sort_unstable).
///
/// # Current implementation
///
/// The current algorithm is an adaptive, iterative merge sort inspired by
/// [timsort](https://en.wikipedia.org/wiki/Timsort).
/// It is designed to be very fast in cases where the slice is nearly sorted, or consists of
/// two or more sorted sequences concatenated one after another.
///
/// Also, it allocates temporary storage half the size of `self`, but for short slices a
/// non-allocating insertion sort is used instead.
/// [Timsort](https://en.wikipedia.org/wiki/Timsort). It is designed to be very fast in cases
/// where the slice is nearly sorted, or consists of two or more sorted sequences concatenated
/// one after another. This implementation is adapted from ipn_stable developed by Lukas
/// Bergdoll, incorporating ideas for a fast bi-directional merge function from quadsort
/// developed by Igor van den Hoven.
///
/// It allocates temporary storage the size of `self`, if this allocation fails it falls back to
/// allocating temporary storage half the size of `self`. For small inputs a non-allocating
/// specialized small-sort is used.
///
/// # Examples
///
Expand Down
12 changes: 11 additions & 1 deletion library/alloc/src/slice/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,17 @@ fn test_sort() {
for i in 0..v.len() {
v[i] = i as i32;
}
v.sort_by(|_, _| *[Less, Equal, Greater].choose(&mut rng).unwrap());

// The original set of elements must be preserved even if Ord is implemented incorrectly, the
// function may return with an unspecified order or may panic. In both cases all observable
// writes, must be observed.

// It's ok to panic on Ord violation or to complete.
// In both cases the original elements must still be present.
let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| {
v.sort_by(|_, _| *[Less, Equal, Greater].choose(&mut rng).unwrap());
}));

v.sort();
for i in 0..v.len() {
assert_eq!(v[i], i as i32);
Expand Down
Loading