about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2022-06-03 17:06:29 -0400
committerRalf Jung <post@ralfj.de>2022-06-05 10:09:41 -0400
commitb96d1e45f188010f2cc6fff956902a455eb2178a (patch)
tree38ce8414a556f123adbc27fe7bc21c0fdafa7e19
parent4322a785cc99ea5fc81dd7f5fc8ba7f7a64b08ef (diff)
downloadrust-b96d1e45f188010f2cc6fff956902a455eb2178a.tar.gz
rust-b96d1e45f188010f2cc6fff956902a455eb2178a.zip
change ptr::swap methods to do untyped copies
-rw-r--r--library/core/src/ptr/mod.rs24
-rw-r--r--library/core/tests/ptr.rs25
2 files changed, 37 insertions, 12 deletions
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 5b04ae7b07e..3b2b7ba8531 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -905,15 +905,15 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
             if mem::align_of::<T>() >= mem::align_of::<$ChunkTy>()
                 && mem::size_of::<T>() % mem::size_of::<$ChunkTy>() == 0
             {
-                let x: *mut MaybeUninit<$ChunkTy> = x.cast();
-                let y: *mut MaybeUninit<$ChunkTy> = y.cast();
+                let x: *mut $ChunkTy = x.cast();
+                let y: *mut $ChunkTy = y.cast();
                 let count = count * (mem::size_of::<T>() / mem::size_of::<$ChunkTy>());
                 // SAFETY: these are the same bytes that the caller promised were
                 // ok, just typed as `MaybeUninit<ChunkTy>`s instead of as `T`s.
                 // The `if` condition above ensures that we're not violating
                 // alignment requirements, and that the division is exact so
                 // that we don't lose any bytes off the end.
-                return unsafe { swap_nonoverlapping_simple(x, y, count) };
+                return unsafe { swap_nonoverlapping_simple_untyped(x, y, count) };
             }
         };
     }
@@ -946,7 +946,7 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
     }
 
     // SAFETY: Same preconditions as this function
-    unsafe { swap_nonoverlapping_simple(x, y, count) }
+    unsafe { swap_nonoverlapping_simple_untyped(x, y, count) }
 }
 
 /// Same behaviour and safety conditions as [`swap_nonoverlapping`]
@@ -955,16 +955,16 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
 /// `swap_nonoverlapping` tries to use) so no need to manually SIMD it.
 #[inline]
 #[rustc_const_unstable(feature = "const_swap", issue = "83163")]
-const unsafe fn swap_nonoverlapping_simple<T>(x: *mut T, y: *mut T, count: usize) {
+const unsafe fn swap_nonoverlapping_simple_untyped<T>(x: *mut T, y: *mut T, count: usize) {
+    let x = x.cast::<MaybeUninit<T>>();
+    let y = y.cast::<MaybeUninit<T>>();
     let mut i = 0;
     while i < count {
-        let x: &mut T =
-            // SAFETY: By precondition, `i` is in-bounds because it's below `n`
-            unsafe { &mut *x.add(i) };
-        let y: &mut T =
-            // SAFETY: By precondition, `i` is in-bounds because it's below `n`
-            // and it's distinct from `x` since the ranges are non-overlapping
-            unsafe { &mut *y.add(i) };
+        // SAFETY: By precondition, `i` is in-bounds because it's below `n`
+        let x = unsafe { &mut *x.add(i) };
+        // SAFETY: By precondition, `i` is in-bounds because it's below `n`
+        // and it's distinct from `x` since the ranges are non-overlapping
+        let y = unsafe { &mut *y.add(i) };
         mem::swap_simple(x, y);
 
         i += 1;
diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs
index 40b2b49bdbd..082d438128e 100644
--- a/library/core/tests/ptr.rs
+++ b/library/core/tests/ptr.rs
@@ -784,6 +784,31 @@ fn nonnull_tagged_pointer_with_provenance() {
 }
 
 #[test]
+fn swap_copy_untyped() {
+    // We call `{swap,copy}{,_nonoverlapping}` at `bool` type on data that is not a valid bool.
+    // These should all do untyped copies, so this should work fine.
+    let mut x = 5u8;
+    let mut y = 6u8;
+
+    let ptr1 = &mut x as *mut u8 as *mut bool;
+    let ptr2 = &mut y as *mut u8 as *mut bool;
+
+    unsafe {
+        ptr::swap(ptr1, ptr2);
+        ptr::swap_nonoverlapping(ptr1, ptr2, 1);
+    }
+    assert_eq!(x, 5);
+    assert_eq!(y, 6);
+
+    unsafe {
+        ptr::copy(ptr1, ptr2, 1);
+        ptr::copy_nonoverlapping(ptr1, ptr2, 1);
+    }
+    assert_eq!(x, 5);
+    assert_eq!(y, 5);
+}
+
+#[test]
 fn test_const_copy() {
     const {
         let ptr1 = &1;