Skip to content

Commit 1afe14c

Browse files
committed
add slice::swap_unchecked
1 parent 1067e2c commit 1afe14c

File tree

1 file changed

+38
-8
lines changed

1 file changed

+38
-8
lines changed

library/core/src/slice/mod.rs

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -560,15 +560,45 @@ impl<T> [T] {
560560
#[stable(feature = "rust1", since = "1.0.0")]
561561
#[inline]
562562
pub fn swap(&mut self, a: usize, b: usize) {
563-
// Can't take two mutable loans from one vector, so instead use raw pointers.
564-
let pa = ptr::addr_of_mut!(self[a]);
565-
let pb = ptr::addr_of_mut!(self[b]);
566-
// SAFETY: `pa` and `pb` have been created from safe mutable references and refer
567-
// to elements in the slice and therefore are guaranteed to be valid and aligned.
568-
// Note that accessing the elements behind `a` and `b` is checked and will
569-
// panic when out of bounds.
563+
assert!(a < self.len());
564+
assert!(b < self.len());
565+
// SAFETY: we just checked that both `a` and `b` are in bounds
566+
unsafe { self.swap_unchecked(a, b) }
567+
}
568+
569+
/// Swaps two elements in the slice, without doing bounds checking.
570+
///
571+
/// For a safe alternative see [`swap`].
572+
///
573+
/// # Arguments
574+
///
575+
/// * a - The index of the first element
576+
/// * b - The index of the second element
577+
///
578+
/// # Safety
579+
///
580+
/// Calling this method with an out-of-bounds index is *[undefined behavior]*.
581+
/// The caller has to ensure that `a < self.len()` and `b < self.len()`.
582+
///
583+
/// # Examples
584+
///
585+
/// ```
586+
/// let mut v = ["a", "b", "c", "d"];
587+
/// // SAFETY: we know that 1 and 3 are both indices of the slice
588+
/// unsafe { v.swap_unchecked(1, 3) };
589+
/// assert!(v == ["a", "d", "c", "b"]);
590+
/// ```
591+
///
592+
/// [`swap`]: slice::swap
593+
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
594+
#[unstable(feature = "slice_swap_unchecked", issue = "88539")]
595+
pub unsafe fn swap_unchecked(&mut self, a: usize, b: usize) {
596+
debug_assert!(a < self.len());
597+
debug_assert!(b < self.len());
598+
let ptr = self.as_mut_ptr();
599+
// SAFETY: caller has to guarantee that `a < self.len()` and `b < self.len()`
570600
unsafe {
571-
ptr::swap(pa, pb);
601+
ptr::swap(ptr.add(a), ptr.add(b));
572602
}
573603
}
574604

0 commit comments

Comments
 (0)