]> git.lizzy.rs Git - rust.git/blobdiff - library/core/src/slice/mod.rs
Rollup merge of #89867 - Urgau:fix-double-definition, r=GuillaumeGomez
[rust.git] / library / core / src / slice / mod.rs
index 53b8b343238d5f1b10b7c4065e6f2ce0d32a71ac..664875a8773eddf596737137fc4f0cadd3322907 100644 (file)
@@ -560,15 +560,52 @@ pub const fn as_mut_ptr_range(&mut self) -> Range<*mut 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.
+        let _ = &self[a];
+        let _ = &self[b];
+
+        // 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
+    ///
+    /// ```
+    /// #![feature(slice_swap_unchecked)]
+    ///
+    /// 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) {
+        #[cfg(debug_assertions)]
+        {
+            let _ = &self[a];
+            let _ = &self[b];
+        }
+
+        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));
         }
     }
 
@@ -675,11 +712,7 @@ pub fn reverse(&mut self) {
             // The resulting pointers `pa` and `pb` are therefore valid and
             // aligned, and can be read from and written to.
             unsafe {
-                // Unsafe swap to avoid the bounds check in safe swap.
-                let ptr = self.as_mut_ptr();
-                let pa = ptr.add(i);
-                let pb = ptr.add(ln - i - 1);
-                ptr::swap(pa, pb);
+                self.swap_unchecked(i, ln - i - 1);
             }
             i += 1;
         }
@@ -2920,9 +2953,6 @@ pub fn fill_with<F>(&mut self, mut f: F)
     ///
     /// The length of `src` must be the same as `self`.
     ///
-    /// If `T` implements `Copy`, it can be more performant to use
-    /// [`copy_from_slice`].
-    ///
     /// # Panics
     ///
     /// This function will panic if the two slices have different lengths.