Skip to content

Commit b96d1e4

Browse files
committed
change ptr::swap methods to do untyped copies
1 parent 4322a78 commit b96d1e4

File tree

2 files changed

+37
-12
lines changed

2 files changed

+37
-12
lines changed

library/core/src/ptr/mod.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -905,15 +905,15 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
905905
if mem::align_of::<T>() >= mem::align_of::<$ChunkTy>()
906906
&& mem::size_of::<T>() % mem::size_of::<$ChunkTy>() == 0
907907
{
908-
let x: *mut MaybeUninit<$ChunkTy> = x.cast();
909-
let y: *mut MaybeUninit<$ChunkTy> = y.cast();
908+
let x: *mut $ChunkTy = x.cast();
909+
let y: *mut $ChunkTy = y.cast();
910910
let count = count * (mem::size_of::<T>() / mem::size_of::<$ChunkTy>());
911911
// SAFETY: these are the same bytes that the caller promised were
912912
// ok, just typed as `MaybeUninit<ChunkTy>`s instead of as `T`s.
913913
// The `if` condition above ensures that we're not violating
914914
// alignment requirements, and that the division is exact so
915915
// that we don't lose any bytes off the end.
916-
return unsafe { swap_nonoverlapping_simple(x, y, count) };
916+
return unsafe { swap_nonoverlapping_simple_untyped(x, y, count) };
917917
}
918918
};
919919
}
@@ -946,7 +946,7 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
946946
}
947947

948948
// SAFETY: Same preconditions as this function
949-
unsafe { swap_nonoverlapping_simple(x, y, count) }
949+
unsafe { swap_nonoverlapping_simple_untyped(x, y, count) }
950950
}
951951

952952
/// 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) {
955955
/// `swap_nonoverlapping` tries to use) so no need to manually SIMD it.
956956
#[inline]
957957
#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
958-
const unsafe fn swap_nonoverlapping_simple<T>(x: *mut T, y: *mut T, count: usize) {
958+
const unsafe fn swap_nonoverlapping_simple_untyped<T>(x: *mut T, y: *mut T, count: usize) {
959+
let x = x.cast::<MaybeUninit<T>>();
960+
let y = y.cast::<MaybeUninit<T>>();
959961
let mut i = 0;
960962
while i < count {
961-
let x: &mut T =
962-
// SAFETY: By precondition, `i` is in-bounds because it's below `n`
963-
unsafe { &mut *x.add(i) };
964-
let y: &mut T =
965-
// SAFETY: By precondition, `i` is in-bounds because it's below `n`
966-
// and it's distinct from `x` since the ranges are non-overlapping
967-
unsafe { &mut *y.add(i) };
963+
// SAFETY: By precondition, `i` is in-bounds because it's below `n`
964+
let x = unsafe { &mut *x.add(i) };
965+
// SAFETY: By precondition, `i` is in-bounds because it's below `n`
966+
// and it's distinct from `x` since the ranges are non-overlapping
967+
let y = unsafe { &mut *y.add(i) };
968968
mem::swap_simple(x, y);
969969

970970
i += 1;

library/core/tests/ptr.rs

+25
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,31 @@ fn nonnull_tagged_pointer_with_provenance() {
783783
}
784784
}
785785

786+
#[test]
787+
fn swap_copy_untyped() {
788+
// We call `{swap,copy}{,_nonoverlapping}` at `bool` type on data that is not a valid bool.
789+
// These should all do untyped copies, so this should work fine.
790+
let mut x = 5u8;
791+
let mut y = 6u8;
792+
793+
let ptr1 = &mut x as *mut u8 as *mut bool;
794+
let ptr2 = &mut y as *mut u8 as *mut bool;
795+
796+
unsafe {
797+
ptr::swap(ptr1, ptr2);
798+
ptr::swap_nonoverlapping(ptr1, ptr2, 1);
799+
}
800+
assert_eq!(x, 5);
801+
assert_eq!(y, 6);
802+
803+
unsafe {
804+
ptr::copy(ptr1, ptr2, 1);
805+
ptr::copy_nonoverlapping(ptr1, ptr2, 1);
806+
}
807+
assert_eq!(x, 5);
808+
assert_eq!(y, 5);
809+
}
810+
786811
#[test]
787812
fn test_const_copy() {
788813
const {

0 commit comments

Comments
 (0)