diff options
| author | ibraheemdev <ibrah1440@gmail.com> | 2021-08-31 12:59:44 -0400 |
|---|---|---|
| committer | Ibraheem Ahmed <ibrah1440@gmail.com> | 2021-10-11 16:14:30 -0400 |
| commit | 1afe14ceedaad19bc3e10dda28ce3f52c69e287a (patch) | |
| tree | 465d375f8f45d6de55ef1c4c2f2c40690b21bef2 | |
| parent | 1067e2ca5e9cfe5c79f956e49ffc684c5142d49b (diff) | |
| download | rust-1afe14ceedaad19bc3e10dda28ce3f52c69e287a.tar.gz rust-1afe14ceedaad19bc3e10dda28ce3f52c69e287a.zip | |
add `slice::swap_unchecked`
| -rw-r--r-- | library/core/src/slice/mod.rs | 46 |
1 files changed, 38 insertions, 8 deletions
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 53b8b343238..2624df78a76 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -560,15 +560,45 @@ impl<T> [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn swap(&mut self, a: usize, b: usize) { - // Can't take two mutable loans from one vector, so instead use raw pointers. - let pa = ptr::addr_of_mut!(self[a]); - let pb = ptr::addr_of_mut!(self[b]); - // SAFETY: `pa` and `pb` have been created from safe mutable references and refer - // to elements in the slice and therefore are guaranteed to be valid and aligned. - // Note that accessing the elements behind `a` and `b` is checked and will - // panic when out of bounds. + assert!(a < self.len()); + assert!(b < self.len()); + // SAFETY: we just checked that both `a` and `b` are in bounds + unsafe { self.swap_unchecked(a, b) } + } + + /// Swaps two elements in the slice, without doing bounds checking. + /// + /// For a safe alternative see [`swap`]. + /// + /// # Arguments + /// + /// * a - The index of the first element + /// * b - The index of the second element + /// + /// # Safety + /// + /// Calling this method with an out-of-bounds index is *[undefined behavior]*. + /// The caller has to ensure that `a < self.len()` and `b < self.len()`. + /// + /// # Examples + /// + /// ``` + /// let mut v = ["a", "b", "c", "d"]; + /// // SAFETY: we know that 1 and 3 are both indices of the slice + /// unsafe { v.swap_unchecked(1, 3) }; + /// assert!(v == ["a", "d", "c", "b"]); + /// ``` + /// + /// [`swap`]: slice::swap + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + #[unstable(feature = "slice_swap_unchecked", issue = "88539")] + pub unsafe fn swap_unchecked(&mut self, a: usize, b: usize) { + debug_assert!(a < self.len()); + debug_assert!(b < self.len()); + let ptr = self.as_mut_ptr(); + // SAFETY: caller has to guarantee that `a < self.len()` and `b < self.len()` unsafe { - ptr::swap(pa, pb); + ptr::swap(ptr.add(a), ptr.add(b)); } } |
