Auto merge of #137412 - scottmcm:redo-swap, r=cuviper
Ensure `swap_nonoverlapping` is really always untyped This replaces #134954, which was arguably overcomplicated. ## Fixes #134713 Actually using the type passed to `ptr::swap_nonoverlapping` for anything other than its size + align turns out to not work, so this goes back to always erasing the types down to just bytes. (Except in `const`, which keeps doing the same thing as before to preserve `@RalfJung's` fix from #134689) ## Fixes #134946 I'd previously moved the swapping to use auto-vectorization *on bytes*, but someone pointed out on Discord that the tail loop handling from that left a whole bunch of byte-by-byte swapping around. This goes back to manual tail handling to avoid that, then still triggers auto-vectorization on pointer-width values. (So you'll see `<4 x i64>` on `x86-64-v3` for example.)
This commit is contained in:
commit
0fe8f3454d
8 changed files with 302 additions and 95 deletions
|
|
@ -0,0 +1,30 @@
|
|||
use std::mem::{size_of, align_of};
|
||||
|
||||
// See <https://github.com/rust-lang/rust/issues/134713>
|
||||
|
||||
#[repr(C)]
|
||||
struct Foo(usize, u8);
|
||||
|
||||
fn main() {
|
||||
let buf1: [usize; 2] = [1000, 2000];
|
||||
let buf2: [usize; 2] = [3000, 4000];
|
||||
|
||||
// Foo and [usize; 2] have the same size and alignment,
|
||||
// so swap_nonoverlapping should treat them the same
|
||||
assert_eq!(size_of::<Foo>(), size_of::<[usize; 2]>());
|
||||
assert_eq!(align_of::<Foo>(), align_of::<[usize; 2]>());
|
||||
|
||||
let mut b1 = buf1;
|
||||
let mut b2 = buf2;
|
||||
// Safety: b1 and b2 are distinct local variables,
|
||||
// with the same size and alignment as Foo.
|
||||
unsafe {
|
||||
std::ptr::swap_nonoverlapping(
|
||||
b1.as_mut_ptr().cast::<Foo>(),
|
||||
b2.as_mut_ptr().cast::<Foo>(),
|
||||
1,
|
||||
);
|
||||
}
|
||||
assert_eq!(b1, buf2);
|
||||
assert_eq!(b2, buf1);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue