From 37ad800cd6188925266f2036ef6e99bae21f332b Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Thu, 27 Jan 2022 15:34:07 -0800 Subject: [PATCH] Add `[f32]::sort_floats` and `[f64]::sort_floats` It's inconvenient to sort a slice or Vec of floats, compared to sorting integers. To simplify numeric code, add a convenience method to `[f32]` and `[f64]` to sort them using `sort_unstable_by` with `total_cmp`. Add lang items slice_f32 and slice_f64 to handle the two new impl blocks. --- compiler/rustc_hir/src/lang_items.rs | 2 + compiler/rustc_span/src/symbol.rs | 2 + .../rustc_typeck/src/check/method/probe.rs | 2 + .../src/coherence/inherent_impls.rs | 22 +++++++ library/core/src/lib.rs | 2 + library/core/src/slice/mod.rs | 62 +++++++++++++++++++ src/librustdoc/clean/types.rs | 10 +-- 7 files changed, 98 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index be4849d0b846e..6996c6d1677b9 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -169,6 +169,8 @@ language_item_table! { Str, sym::str, str_impl, Target::Impl, GenericRequirement::None; Array, sym::array, array_impl, Target::Impl, GenericRequirement::None; Slice, sym::slice, slice_impl, Target::Impl, GenericRequirement::None; + SliceF32, sym::slice_f32, slice_f32_impl, Target::Impl, GenericRequirement::None; + SliceF64, sym::slice_f64, slice_f64_impl, Target::Impl, GenericRequirement::None; SliceU8, sym::slice_u8, slice_u8_impl, Target::Impl, GenericRequirement::None; StrAlloc, sym::str_alloc, str_alloc_impl, Target::Impl, GenericRequirement::None; SliceAlloc, sym::slice_alloc, slice_alloc_impl, Target::Impl, GenericRequirement::None; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d99bdd3bdd5be..0b714a801dc27 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1295,6 +1295,8 @@ symbols! { skip, slice, slice_alloc, + slice_f32, + slice_f64, slice_len_fn, slice_patterns, slice_u8, diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 9efaa37633e3e..78230f6274d26 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -668,6 +668,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { ty::Slice(_) => { for lang_def_id in [ lang_items.slice_impl(), + lang_items.slice_f32_impl(), + lang_items.slice_f64_impl(), lang_items.slice_u8_impl(), lang_items.slice_alloc_impl(), lang_items.slice_u8_alloc_impl(), diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs index f4e5cce0129c9..aacfad5029aea 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs @@ -114,6 +114,28 @@ impl<'tcx> ItemLikeVisitor<'_> for InherentCollect<'tcx> { assoc_items, ); } + ty::Slice(slice_item) if slice_item == self.tcx.types.f32 => { + self.check_primitive_impl( + item.def_id, + lang_items.slice_f32_impl(), + None, + "slice_f32", + "[f32]", + item.span, + assoc_items, + ); + } + ty::Slice(slice_item) if slice_item == self.tcx.types.f64 => { + self.check_primitive_impl( + item.def_id, + lang_items.slice_f64_impl(), + None, + "slice_f64", + "[f64]", + item.span, + assoc_items, + ); + } ty::Slice(_) => { self.check_primitive_impl( item.def_id, diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index d8ac816fb15a0..cc83f1a9925b4 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -151,6 +151,8 @@ #![feature(variant_count)] #![feature(const_array_from_ref)] #![feature(const_slice_from_ref)] +// Library features: +#![feature(total_cmp)] // // Language features: #![feature(abi_unadjusted)] diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 0599f27401394..e6178b912f482 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3983,6 +3983,68 @@ impl [T] { } } +#[cfg(not(bootstrap))] +#[cfg(not(test))] +#[lang = "slice_f32"] +impl [f32] { + /// Sorts the slice of floats. + /// + /// This sort is in-place (i.e. does not allocate), *O*(*n* \* log(*n*)) worst-case, and uses + /// the ordering defined by [`f32::total_cmp`]. + /// + /// # Current implementation + /// + /// This uses the same sorting algorithm as [`sort_unstable_by`](slice::sort_unstable_by). + /// + /// # Examples + /// + /// ``` + /// #![feature(sort_floats)] + /// let mut v = [2.6, -5e-8, f32::NAN, 8.29, f32::INFINITY, -1.0, 0.0, -f32::INFINITY, -0.0]; + /// + /// v.sort_floats(); + /// let sorted = [-f32::INFINITY, -1.0, -5e-8, -0.0, 0.0, 2.6, 8.29, f32::INFINITY, f32::NAN]; + /// assert_eq!(&v[..8], &sorted[..8]); + /// assert!(v[8].is_nan()); + /// ``` + #[unstable(feature = "sort_floats", issue = "93396")] + #[inline] + pub fn sort_floats(&mut self) { + self.sort_unstable_by(f32::total_cmp); + } +} + +#[cfg(not(bootstrap))] +#[cfg(not(test))] +#[lang = "slice_f64"] +impl [f64] { + /// Sorts the slice of floats. + /// + /// This sort is in-place (i.e. does not allocate), *O*(*n* \* log(*n*)) worst-case, and uses + /// the ordering defined by [`f64::total_cmp`]. + /// + /// # Current implementation + /// + /// This uses the same sorting algorithm as [`sort_unstable_by`](slice::sort_unstable_by). + /// + /// # Examples + /// + /// ``` + /// #![feature(sort_floats)] + /// let mut v = [2.6, -5e-8, f64::NAN, 8.29, f64::INFINITY, -1.0, 0.0, -f64::INFINITY, -0.0]; + /// + /// v.sort_floats(); + /// let sorted = [-f64::INFINITY, -1.0, -5e-8, -0.0, 0.0, 2.6, 8.29, f64::INFINITY, f64::NAN]; + /// assert_eq!(&v[..8], &sorted[..8]); + /// assert!(v[8].is_nan()); + /// ``` + #[unstable(feature = "sort_floats", issue = "93396")] + #[inline] + pub fn sort_floats(&mut self) { + self.sort_unstable_by(f64::total_cmp); + } +} + trait CloneFromSpec { fn spec_clone_from(&mut self, src: &[T]); } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index d34c2dba0b0dd..d142024f20301 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1648,18 +1648,18 @@ impl PrimitiveType { } } - crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static ArrayVec { + crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static ArrayVec { Self::all_impls(tcx).get(self).expect("missing impl for primitive type") } - crate fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap> { - static CELL: OnceCell>> = OnceCell::new(); + crate fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap> { + static CELL: OnceCell>> = OnceCell::new(); CELL.get_or_init(move || { use self::PrimitiveType::*; let single = |a: Option| a.into_iter().collect(); - let both = |a: Option, b: Option| -> ArrayVec<_, 4> { + let both = |a: Option, b: Option| -> ArrayVec<_, 6> { a.into_iter().chain(b).collect() }; @@ -1686,6 +1686,8 @@ impl PrimitiveType { lang_items .slice_impl() .into_iter() + .chain(lang_items.slice_f32_impl()) + .chain(lang_items.slice_f64_impl()) .chain(lang_items.slice_u8_impl()) .chain(lang_items.slice_alloc_impl()) .chain(lang_items.slice_u8_alloc_impl())