@@ -560,15 +560,52 @@ impl<T> [T] {
560
560
#[stable(feature = "rust1", since = "1.0.0")]
561
561
#[inline]
562
562
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
+ let _ = &self[a];
564
+ let _ = &self[b];
565
+
566
+ // SAFETY: we just checked that both `a` and `b` are in bounds
567
+ unsafe { self.swap_unchecked(a, b) }
568
+ }
569
+
570
+ /// Swaps two elements in the slice, without doing bounds checking.
571
+ ///
572
+ /// For a safe alternative see [`swap`].
573
+ ///
574
+ /// # Arguments
575
+ ///
576
+ /// * a - The index of the first element
577
+ /// * b - The index of the second element
578
+ ///
579
+ /// # Safety
580
+ ///
581
+ /// Calling this method with an out-of-bounds index is *[undefined behavior]*.
582
+ /// The caller has to ensure that `a < self.len()` and `b < self.len()`.
583
+ ///
584
+ /// # Examples
585
+ ///
586
+ /// ```
587
+ /// #![feature(slice_swap_unchecked)]
588
+ ///
589
+ /// let mut v = ["a", "b", "c", "d"];
590
+ /// // SAFETY: we know that 1 and 3 are both indices of the slice
591
+ /// unsafe { v.swap_unchecked(1, 3) };
592
+ /// assert!(v == ["a", "d", "c", "b"]);
593
+ /// ```
594
+ ///
595
+ /// [`swap`]: slice::swap
596
+ /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
597
+ #[unstable(feature = "slice_swap_unchecked", issue = "88539")]
598
+ pub unsafe fn swap_unchecked(&mut self, a: usize, b: usize) {
599
+ #[cfg(debug_assertions)]
600
+ {
601
+ let _ = &self[a];
602
+ let _ = &self[b];
603
+ }
604
+
605
+ let ptr = self.as_mut_ptr();
606
+ // SAFETY: caller has to guarantee that `a < self.len()` and `b < self.len()`
570
607
unsafe {
571
- ptr::swap(pa, pb );
608
+ ptr::swap(ptr.add(a), ptr.add(b) );
572
609
}
573
610
}
574
611
@@ -675,11 +712,7 @@ impl<T> [T] {
675
712
// The resulting pointers `pa` and `pb` are therefore valid and
676
713
// aligned, and can be read from and written to.
677
714
unsafe {
678
- // Unsafe swap to avoid the bounds check in safe swap.
679
- let ptr = self.as_mut_ptr();
680
- let pa = ptr.add(i);
681
- let pb = ptr.add(ln - i - 1);
682
- ptr::swap(pa, pb);
715
+ self.swap_unchecked(i, ln - i - 1);
683
716
}
684
717
i += 1;
685
718
}
0 commit comments