@@ -178,15 +178,25 @@ impl<T> [T] {
178178 /// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*))
179179 /// worst-case.
180180 ///
181- /// If `T: Ord` does not implement a total order the resulting order is unspecified. All
182- /// original elements will remain in the slice and any possible modifications via interior
183- /// mutability are observed in the input. Same is true if `T: Ord` panics.
181+ /// If the implementation of [`Ord`] for `T` does not implement a [total order] the resulting
182+ /// order of elements in the slice is unspecified. All original elements will remain in the
183+ /// slice and any possible modifications via interior mutability are observed in the input. Same
184+ /// is true if the implementation of [`Ord`] for `T` panics.
184185 ///
185186 /// When applicable, unstable sorting is preferred because it is generally faster than stable
186187 /// sorting and it doesn't allocate auxiliary memory. See
187188 /// [`sort_unstable`](slice::sort_unstable). The exception are partially sorted slices, which
188189 /// may be better served with `slice::sort`.
189190 ///
191+ /// Sorting types that only implement [`PartialOrd`] such as [`f32`] and [`f64`] require
192+ /// additional precautions. For example, `f32::NAN != f32::NAN`, which doesn't fulfill the
193+ /// reflexivity requirement of [`Ord`]. By using an alternative comparison function with
194+ /// `slice::sort_by` such as [`f32::total_cmp`] or [`f64::total_cmp`] that defines a [total
195+ /// order] users can sort slices containing floating-point values. Alternatively, if all values
196+ /// in the slice are guaranteed to be in a subset for which [`PartialOrd::partial_cmp`] forms a
197+ /// [total order], it's possible to sort the slice with `sort_by(|a, b|
198+ /// a.partial_cmp(b).unwrap())`.
199+ ///
190200 /// # Current implementation
191201 ///
192202 /// The current implementation is based on [driftsort] by Orson Peters and Lukas Bergdoll, which
@@ -198,18 +208,21 @@ impl<T> [T] {
198208 /// handled without allocation, medium sized slices allocate `self.len()` and beyond that it
199209 /// clamps at `self.len() / 2`.
200210 ///
201- /// If `T: Ord` does not implement a total order, the implementation may panic.
211+ /// # Panics
212+ ///
213+ /// May panic if the implementation of [`Ord`] for `T` does not implement a [total order].
202214 ///
203215 /// # Examples
204216 ///
205217 /// ```
206- /// let mut v = [-5, 4 , 1, -3, 2];
218+ /// let mut v = [4, -5 , 1, -3, 2];
207219 ///
208220 /// v.sort();
209- /// assert !(v == [-5, -3, 1, 2, 4]);
221+ /// assert_eq !(v, [-5, -3, 1, 2, 4]);
210222 /// ```
211223 ///
212224 /// [driftsort]: https://github.com/Voultapher/driftsort
225+ /// [total order]: https://en.wikipedia.org/wiki/Total_order
213226 #[ cfg( not( no_global_oom_handling) ) ]
214227 #[ rustc_allow_incoherent_impl]
215228 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -221,30 +234,19 @@ impl<T> [T] {
221234 stable_sort ( self , T :: lt) ;
222235 }
223236
224- /// Sorts the slice with a comparator function, preserving initial order of equal elements.
237+ /// Sorts the slice with a comparison function, preserving initial order of equal elements.
225238 ///
226239 /// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*))
227240 /// worst-case.
228241 ///
229- /// The comparator function should define a total ordering for the elements in the slice. If the
230- /// ordering is not total, the order of the elements is unspecified.
231- ///
232- /// If the comparator function does not implement a total order the resulting order is
233- /// unspecified. All original elements will remain in the slice and any possible modifications
234- /// via interior mutability are observed in the input. Same is true if the comparator function
235- /// panics. A total order (for all `a`, `b` and `c`):
242+ /// If the comparison function `compare` does not implement a [total order] the resulting order
243+ /// of elements in the slice is unspecified. All original elements will remain in the slice and
244+ /// any possible modifications via interior mutability are observed in the input. Same is true
245+ /// if `compare` panics.
236246 ///
237- /// * total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is true, and
238- /// * transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
239- ///
240- /// For example, while [`f64`] doesn't implement [`Ord`] because `NaN != NaN`, we can use
241- /// `partial_cmp` as our sort function when we know the slice doesn't contain a `NaN`.
242- ///
243- /// ```
244- /// let mut floats = [5f64, 4.0, 1.0, 3.0, 2.0];
245- /// floats.sort_unstable_by(|a, b| a.partial_cmp(b).unwrap());
246- /// assert_eq!(floats, [1.0, 2.0, 3.0, 4.0, 5.0]);
247- /// ```
247+ /// For example `|a, b| (a - b).cmp(a)` is a comparison function that is neither transitive nor
248+ /// reflexive nor total, `a < b < c < a` with `a = 1, b = 2, c = 3`. For more information and
249+ /// examples see the [`Ord`] documentation.
248250 ///
249251 /// # Current implementation
250252 ///
@@ -257,21 +259,24 @@ impl<T> [T] {
257259 /// handled without allocation, medium sized slices allocate `self.len()` and beyond that it
258260 /// clamps at `self.len() / 2`.
259261 ///
260- /// If `T: Ord` does not implement a total order, the implementation may panic.
262+ /// # Panics
263+ ///
264+ /// May panic if `compare` does not implement a [total order].
261265 ///
262266 /// # Examples
263267 ///
264268 /// ```
265- /// let mut v = [5, 4 , 1, 3, 2];
269+ /// let mut v = [4, -5 , 1, - 3, 2];
266270 /// v.sort_by(|a, b| a.cmp(b));
267- /// assert !(v == [1, 2, 3, 4, 5 ]);
271+ /// assert_eq !(v, [-5, -3, 1, 2, 4 ]);
268272 ///
269273 /// // reverse sorting
270274 /// v.sort_by(|a, b| b.cmp(a));
271- /// assert !(v == [5, 4, 3, 2, 1 ]);
275+ /// assert_eq !(v, [4, 2, 1, -3, -5 ]);
272276 /// ```
273277 ///
274278 /// [driftsort]: https://github.com/Voultapher/driftsort
279+ /// [total order]: https://en.wikipedia.org/wiki/Total_order
275280 #[ cfg( not( no_global_oom_handling) ) ]
276281 #[ rustc_allow_incoherent_impl]
277282 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -288,9 +293,10 @@ impl<T> [T] {
288293 /// This sort is stable (i.e., does not reorder equal elements) and *O*(*m* \* *n* \* log(*n*))
289294 /// worst-case, where the key function is *O*(*m*).
290295 ///
291- /// If `K: Ord` does not implement a total order the resulting order is unspecified.
292- /// All original elements will remain in the slice and any possible modifications via interior
293- /// mutability are observed in the input. Same is true if `K: Ord` panics.
296+ /// If the implementation of [`Ord`] for `K` does not implement a [total order] the resulting
297+ /// order of elements in the slice is unspecified. All original elements will remain in the
298+ /// slice and any possible modifications via interior mutability are observed in the input. Same
299+ /// is true if the implementation of [`Ord`] for `K` panics.
294300 ///
295301 /// # Current implementation
296302 ///
@@ -303,18 +309,21 @@ impl<T> [T] {
303309 /// handled without allocation, medium sized slices allocate `self.len()` and beyond that it
304310 /// clamps at `self.len() / 2`.
305311 ///
306- /// If `K: Ord` does not implement a total order, the implementation may panic.
312+ /// # Panics
313+ ///
314+ /// May panic if the implementation of [`Ord`] for `K` does not implement a [total order].
307315 ///
308316 /// # Examples
309317 ///
310318 /// ```
311- /// let mut v = [-5i32, 4 , 1, -3, 2];
319+ /// let mut v = [4i32, -5 , 1, -3, 2];
312320 ///
313321 /// v.sort_by_key(|k| k.abs());
314- /// assert !(v == [1, 2, -3, 4, -5]);
322+ /// assert_eq !(v, [1, 2, -3, 4, -5]);
315323 /// ```
316324 ///
317325 /// [driftsort]: https://github.com/Voultapher/driftsort
326+ /// [total order]: https://en.wikipedia.org/wiki/Total_order
318327 #[ cfg( not( no_global_oom_handling) ) ]
319328 #[ rustc_allow_incoherent_impl]
320329 #[ stable( feature = "slice_sort_by_key" , since = "1.7.0" ) ]
@@ -336,9 +345,10 @@ impl<T> [T] {
336345 /// storage to remember the results of key evaluation. The order of calls to the key function is
337346 /// unspecified and may change in future versions of the standard library.
338347 ///
339- /// If `K: Ord` does not implement a total order the resulting order is unspecified.
340- /// All original elements will remain in the slice and any possible modifications via interior
341- /// mutability are observed in the input. Same is true if `K: Ord` panics.
348+ /// If the implementation of [`Ord`] for `K` does not implement a [total order] the resulting
349+ /// order of elements in the slice is unspecified. All original elements will remain in the
350+ /// slice and any possible modifications via interior mutability are observed in the input. Same
351+ /// is true if the implementation of [`Ord`] for `K` panics.
342352 ///
343353 /// For simple key functions (e.g., functions that are property accesses or basic operations),
344354 /// [`sort_by_key`](slice::sort_by_key) is likely to be faster.
@@ -355,16 +365,22 @@ impl<T> [T] {
355365 /// In the worst case, the algorithm allocates temporary storage in a `Vec<(K, usize)>` the
356366 /// length of the slice.
357367 ///
368+ /// # Panics
369+ ///
370+ /// May panic if the implementation of [`Ord`] for `K` does not implement a [total order].
371+ ///
358372 /// # Examples
359373 ///
360374 /// ```
361- /// let mut v = [-5i32, 4, 32 , -3, 2];
375+ /// let mut v = [4i32, -5, 1 , -3, 2, 10 ];
362376 ///
377+ /// // Strings are sorted by lexicographical order.
363378 /// v.sort_by_cached_key(|k| k.to_string());
364- /// assert !(v == [-3, -5, 2, 32 , 4]);
379+ /// assert_eq !(v, [-3, -5, 1, 10, 2 , 4]);
365380 /// ```
366381 ///
367382 /// [ipnsort]: https://github.com/Voultapher/sort-research-rs/tree/main/ipnsort
383+ /// [total order]: https://en.wikipedia.org/wiki/Total_order
368384 #[ cfg( not( no_global_oom_handling) ) ]
369385 #[ rustc_allow_incoherent_impl]
370386 #[ stable( feature = "slice_sort_by_cached_key" , since = "1.34.0" ) ]
0 commit comments