diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index c7960b3fb49c3..b404bd6f2f1bb 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -41,6 +41,8 @@ pub use core::slice::ArrayChunksMut; pub use core::slice::ArrayWindows; #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] pub use core::slice::EscapeAscii; +#[stable(feature = "get_many_mut", since = "CURRENT_RUSTC_VERSION")] +pub use core::slice::GetManyMutError; #[stable(feature = "slice_get_slice", since = "1.28.0")] pub use core::slice::SliceIndex; #[stable(feature = "from_ref", since = "1.28.0")] diff --git a/library/core/src/error.rs b/library/core/src/error.rs index 19b7bb44f855a..e252df6d5441e 100644 --- a/library/core/src/error.rs +++ b/library/core/src/error.rs @@ -1076,5 +1076,5 @@ impl Error for crate::time::TryFromFloatSecsError {} #[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")] impl Error for crate::ffi::FromBytesUntilNulError {} -#[unstable(feature = "get_many_mut", issue = "104642")] +#[stable(feature = "get_many_mut", since = "CURRENT_RUSTC_VERSION")] impl Error for crate::slice::GetManyMutError {} diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 8b502624176b6..abaa8ce28a21c 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -4448,12 +4448,10 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(get_many_mut)] - /// /// let x = &mut [1, 2, 4]; /// /// unsafe { - /// let [a, b] = x.get_many_unchecked_mut([0, 2]); + /// let [a, b] = x.get_many_unchecked_mut(&[0, 2]); /// *a *= 10; /// *b *= 100; /// } @@ -4462,11 +4460,11 @@ impl [T] { /// /// [`get_many_mut`]: slice::get_many_mut /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html - #[unstable(feature = "get_many_mut", issue = "104642")] + #[stable(feature = "get_many_mut", since = "CURRENT_RUSTC_VERSION")] #[inline] pub unsafe fn get_many_unchecked_mut( &mut self, - indices: [usize; N], + indices: &[usize; N], ) -> [&mut T; N] { // NB: This implementation is written as it is because any variation of // `indices.map(|i| self.get_unchecked_mut(i))` would make miri unhappy, @@ -4495,22 +4493,20 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(get_many_mut)] - /// /// let v = &mut [1, 2, 3]; - /// if let Ok([a, b]) = v.get_many_mut([0, 2]) { + /// if let Ok([a, b]) = v.get_many_mut(&[0, 2]) { /// *a = 413; /// *b = 612; /// } /// assert_eq!(v, &[413, 2, 612]); /// ``` - #[unstable(feature = "get_many_mut", issue = "104642")] + #[stable(feature = "get_many_mut", since = "CURRENT_RUSTC_VERSION")] #[inline] pub fn get_many_mut( &mut self, - indices: [usize; N], + indices: &[usize; N], ) -> Result<[&mut T; N], GetManyMutError> { - if !get_many_check_valid(&indices, self.len()) { + if !get_many_check_valid(indices, self.len()) { return Err(GetManyMutError { _private: () }); } // SAFETY: The `get_many_check_valid()` call checked that all indices @@ -4851,20 +4847,30 @@ impl SlicePattern for [T; N] { } /// This checks every index against each other, and against `len`. -/// -/// This will do `binomial(N + 1, 2) = N * (N + 1) / 2 = 0, 1, 3, 6, 10, ..` -/// comparison operations. fn get_many_check_valid(indices: &[usize; N], len: usize) -> bool { - // NB: The optimizer should inline the loops into a sequence - // of instructions without additional branching. - let mut valid = true; - for (i, &idx) in indices.iter().enumerate() { - valid &= idx < len; - for &idx2 in &indices[..i] { - valid &= idx != idx2; + // Based on benchmarks, it is faster to sort starting with 9 indices. + if N >= 9 { + let mut sorted_indices = *indices; + sorted_indices.sort_unstable(); + for &[i, j] in sorted_indices.array_windows() { + if i == j { + return false; + } } + let biggest_index = *sorted_indices.last().expect("indices array should not be empty"); + biggest_index < len + } else { + // NB: The optimizer should inline the loops into a sequence + // of instructions without additional branching. + let mut valid = true; + for (i, &idx) in indices.iter().enumerate() { + valid &= idx < len; + for &idx2 in &indices[..i] { + valid &= idx != idx2; + } + } + valid } - valid } /// The error type returned by [`get_many_mut`][`slice::get_many_mut`]. @@ -4876,27 +4882,25 @@ fn get_many_check_valid(indices: &[usize; N], len: usize) -> boo /// # Examples /// /// ``` -/// #![feature(get_many_mut)] -/// /// let v = &mut [1, 2, 3]; -/// assert!(v.get_many_mut([0, 999]).is_err()); -/// assert!(v.get_many_mut([1, 1]).is_err()); +/// assert!(v.get_many_mut(&[0, 999]).is_err()); +/// assert!(v.get_many_mut(&[1, 1]).is_err()); /// ``` -#[unstable(feature = "get_many_mut", issue = "104642")] -// NB: The N here is there to be forward-compatible with adding more details -// to the error type at a later point +#[stable(feature = "get_many_mut", since = "CURRENT_RUSTC_VERSION")] +// NB: The N and the private field here is there to be forward-compatible with +// adding more details to the error type at a later point pub struct GetManyMutError { _private: (), } -#[unstable(feature = "get_many_mut", issue = "104642")] +#[stable(feature = "get_many_mut", since = "CURRENT_RUSTC_VERSION")] impl fmt::Debug for GetManyMutError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("GetManyMutError").finish_non_exhaustive() } } -#[unstable(feature = "get_many_mut", issue = "104642")] +#[stable(feature = "get_many_mut", since = "CURRENT_RUSTC_VERSION")] impl fmt::Display for GetManyMutError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt("an index is out of bounds or appeared multiple times in the array", f) diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 51d57c9e37d7c..e16c7740e38b1 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -110,7 +110,6 @@ #![feature(error_generic_member_access)] #![feature(trait_upcasting)] #![feature(is_ascii_octdigit)] -#![feature(get_many_mut)] #![feature(iter_map_windows)] #![allow(internal_features)] #![deny(unsafe_op_in_unsafe_fn)] diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 4cbbabb672ba0..f3e7d27dc77af 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -2599,7 +2599,7 @@ fn test_flatten_mut_size_overflow() { #[test] fn test_get_many_mut_normal_2() { let mut v = vec![1, 2, 3, 4, 5]; - let [a, b] = v.get_many_mut([3, 0]).unwrap(); + let [a, b] = v.get_many_mut(&[3, 0]).unwrap(); *a += 10; *b += 100; assert_eq!(v, vec![101, 2, 3, 14, 5]); @@ -2608,7 +2608,7 @@ fn test_get_many_mut_normal_2() { #[test] fn test_get_many_mut_normal_3() { let mut v = vec![1, 2, 3, 4, 5]; - let [a, b, c] = v.get_many_mut([0, 4, 2]).unwrap(); + let [a, b, c] = v.get_many_mut(&[0, 4, 2]).unwrap(); *a += 10; *b += 100; *c += 1000; @@ -2618,14 +2618,14 @@ fn test_get_many_mut_normal_3() { #[test] fn test_get_many_mut_empty() { let mut v = vec![1, 2, 3, 4, 5]; - let [] = v.get_many_mut([]).unwrap(); + let [] = v.get_many_mut(&[]).unwrap(); assert_eq!(v, vec![1, 2, 3, 4, 5]); } #[test] fn test_get_many_mut_single_first() { let mut v = vec![1, 2, 3, 4, 5]; - let [a] = v.get_many_mut([0]).unwrap(); + let [a] = v.get_many_mut(&[0]).unwrap(); *a += 10; assert_eq!(v, vec![11, 2, 3, 4, 5]); } @@ -2633,7 +2633,7 @@ fn test_get_many_mut_single_first() { #[test] fn test_get_many_mut_single_last() { let mut v = vec![1, 2, 3, 4, 5]; - let [a] = v.get_many_mut([4]).unwrap(); + let [a] = v.get_many_mut(&[4]).unwrap(); *a += 10; assert_eq!(v, vec![1, 2, 3, 4, 15]); } @@ -2641,19 +2641,19 @@ fn test_get_many_mut_single_last() { #[test] fn test_get_many_mut_oob_nonempty() { let mut v = vec![1, 2, 3, 4, 5]; - assert!(v.get_many_mut([5]).is_err()); + assert!(v.get_many_mut(&[5]).is_err()); } #[test] fn test_get_many_mut_oob_empty() { let mut v: Vec = vec![]; - assert!(v.get_many_mut([0]).is_err()); + assert!(v.get_many_mut(&[0]).is_err()); } #[test] fn test_get_many_mut_duplicate() { let mut v = vec![1, 2, 3, 4, 5]; - assert!(v.get_many_mut([1, 3, 3, 4]).is_err()); + assert!(v.get_many_mut(&[1, 3, 3, 4]).is_err()); } #[test] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 9fba657d116de..0e6443c676ac8 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -392,7 +392,6 @@ #![feature(custom_test_frameworks)] #![feature(edition_panic)] #![feature(format_args_nl)] -#![feature(get_many_mut)] #![feature(log_syntax)] #![feature(test)] #![feature(trace_macros)]