@@ -560,15 +560,52 @@ 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+ 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()`
570607 unsafe {
571- ptr:: swap ( pa , pb ) ;
608+ ptr:: swap ( ptr . add ( a ) , ptr . add ( b ) ) ;
572609 }
573610 }
574611
@@ -675,11 +712,7 @@ impl<T> [T] {
675712 // The resulting pointers `pa` and `pb` are therefore valid and
676713 // aligned, and can be read from and written to.
677714 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 ) ;
683716 }
684717 i += 1 ;
685718 }
0 commit comments