From 3751e133bca55dbec521ccb36132fa0bdbf10b88 Mon Sep 17 00:00:00 2001 From: okaneco <47607823+okaneco@users.noreply.github.com> Date: Sat, 5 Jul 2025 22:26:40 -0400 Subject: [PATCH] slice: Mark `rotate_left`, `rotate_right` unstably const --- library/core/src/slice/mod.rs | 6 ++++-- library/core/src/slice/rotate.rs | 24 +++++++++++++++++------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index dc09ba8d788fc..7df717751f522 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3668,7 +3668,8 @@ impl [T] { /// assert_eq!(a, ['a', 'c', 'd', 'e', 'b', 'f']); /// ``` #[stable(feature = "slice_rotate", since = "1.26.0")] - pub fn rotate_left(&mut self, mid: usize) { + #[rustc_const_unstable(feature = "const_slice_rotate", issue = "143812")] + pub const fn rotate_left(&mut self, mid: usize) { assert!(mid <= self.len()); let k = self.len() - mid; let p = self.as_mut_ptr(); @@ -3713,7 +3714,8 @@ impl [T] { /// assert_eq!(a, ['a', 'e', 'b', 'c', 'd', 'f']); /// ``` #[stable(feature = "slice_rotate", since = "1.26.0")] - pub fn rotate_right(&mut self, k: usize) { + #[rustc_const_unstable(feature = "const_slice_rotate", issue = "143812")] + pub const fn rotate_right(&mut self, k: usize) { assert!(k <= self.len()); let mid = self.len() - k; let p = self.as_mut_ptr(); diff --git a/library/core/src/slice/rotate.rs b/library/core/src/slice/rotate.rs index 80178f297eaae..b3b64422884d5 100644 --- a/library/core/src/slice/rotate.rs +++ b/library/core/src/slice/rotate.rs @@ -1,5 +1,5 @@ use crate::mem::{MaybeUninit, SizedTypeProperties}; -use crate::{cmp, ptr}; +use crate::ptr; type BufType = [usize; 32]; @@ -11,7 +11,7 @@ type BufType = [usize; 32]; /// /// The specified range must be valid for reading and writing. #[inline] -pub(super) unsafe fn ptr_rotate(left: usize, mid: *mut T, right: usize) { +pub(super) const unsafe fn ptr_rotate(left: usize, mid: *mut T, right: usize) { if T::IS_ZST { return; } @@ -21,7 +21,8 @@ pub(super) unsafe fn ptr_rotate(left: usize, mid: *mut T, right: usize) { } // `T` is not a zero-sized type, so it's okay to divide by its size. if !cfg!(feature = "optimize_for_size") - && cmp::min(left, right) <= size_of::() / size_of::() + // FIXME(const-hack): Use cmp::min when available in const + && const_min(left, right) <= size_of::() / size_of::() { // SAFETY: guaranteed by the caller unsafe { ptr_rotate_memmove(left, mid, right) }; @@ -45,7 +46,7 @@ pub(super) unsafe fn ptr_rotate(left: usize, mid: *mut T, right: usize) { /// /// The specified range must be valid for reading and writing. #[inline] -unsafe fn ptr_rotate_memmove(left: usize, mid: *mut T, right: usize) { +const unsafe fn ptr_rotate_memmove(left: usize, mid: *mut T, right: usize) { // The `[T; 0]` here is to ensure this is appropriately aligned for T let mut rawarray = MaybeUninit::<(BufType, [T; 0])>::uninit(); let buf = rawarray.as_mut_ptr() as *mut T; @@ -117,7 +118,7 @@ unsafe fn ptr_rotate_memmove(left: usize, mid: *mut T, right: usize) { /// /// The specified range must be valid for reading and writing. #[inline] -unsafe fn ptr_rotate_gcd(left: usize, mid: *mut T, right: usize) { +const unsafe fn ptr_rotate_gcd(left: usize, mid: *mut T, right: usize) { // Algorithm 2 // Microbenchmarks indicate that the average performance for random shifts is better all // the way until about `left + right == 32`, but the worst case performance breaks even @@ -175,7 +176,9 @@ unsafe fn ptr_rotate_gcd(left: usize, mid: *mut T, right: usize) { } } // finish the chunk with more rounds - for start in 1..gcd { + // FIXME(const-hack): Use `for start in 1..gcd` when available in const + let mut start = 1; + while start < gcd { // SAFETY: `gcd` is at most equal to `right` so all values in `1..gcd` are valid for // reading and writing as per the function's safety contract, see [long-safety-expl] // above @@ -201,6 +204,8 @@ unsafe fn ptr_rotate_gcd(left: usize, mid: *mut T, right: usize) { i += right; } } + + start += 1; } } @@ -222,7 +227,7 @@ unsafe fn ptr_rotate_gcd(left: usize, mid: *mut T, right: usize) { /// /// The specified range must be valid for reading and writing. #[inline] -unsafe fn ptr_rotate_swap(mut left: usize, mut mid: *mut T, mut right: usize) { +const unsafe fn ptr_rotate_swap(mut left: usize, mut mid: *mut T, mut right: usize) { loop { if left >= right { // Algorithm 3 @@ -265,3 +270,8 @@ unsafe fn ptr_rotate_swap(mut left: usize, mut mid: *mut T, mut right: usize) } } } + +// FIXME(const-hack): Use cmp::min when available in const +const fn const_min(left: usize, right: usize) -> usize { + if right < left { right } else { left } +}