diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index ea263d05017..9940673fd4c 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -731,38 +731,6 @@ pub const fn swap(x: &mut T, y: &mut T) { unsafe { intrinsics::typed_swap(x, y) } } -/// Same as [`swap`] semantically, but always uses the simple implementation. -/// -/// Used elsewhere in `mem` and `ptr` at the bottom layer of calls. -#[rustc_const_unstable(feature = "const_swap", issue = "83163")] -#[inline] -pub(crate) const fn swap_simple(x: &mut T, y: &mut T) { - // We arrange for this to typically be called with small types, - // so this reads-and-writes approach is actually better than using - // copy_nonoverlapping as it easily puts things in LLVM registers - // directly and doesn't end up inlining allocas. - // And LLVM actually optimizes it to 3Ă—memcpy if called with - // a type larger than it's willing to keep in a register. - // Having typed reads and writes in MIR here is also good as - // it lets Miri and CTFE understand them better, including things - // like enforcing type validity for them. - // Importantly, read+copy_nonoverlapping+write introduces confusing - // asymmetry to the behaviour where one value went through read+write - // whereas the other was copied over by the intrinsic (see #94371). - // Furthermore, using only read+write here benefits limited backends - // such as SPIR-V that work on an underlying *typed* view of memory, - // and thus have trouble with Rust's untyped memory operations. - - // SAFETY: exclusive references are always valid to read/write, - // including being aligned, and nothing here panics so it's drop-safe. - unsafe { - let a = ptr::read(x); - let b = ptr::read(y); - ptr::write(x, b); - ptr::write(y, a); - } -} - /// Replaces `dest` with the default value of `T`, returning the previous `dest` value. /// /// * If you want to replace the values of two variables, see [`swap`]. diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 30af7522368..e0eb03da358 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1062,11 +1062,26 @@ const unsafe fn swap_nonoverlapping_simple_untyped(x: *mut T, y: *mut T, coun let mut i = 0; while i < count { // SAFETY: By precondition, `i` is in-bounds because it's below `n` - let x = unsafe { &mut *x.add(i) }; + let x = unsafe { 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); + let y = unsafe { y.add(i) }; + + // If we end up here, it's because we're using a simple type -- like + // a small power-of-two-sized thing -- or a special type with particularly + // large alignment, particularly SIMD types. + // Thus we're fine just reading-and-writing it, as either it's small + // and that works well anyway or it's special and the type's author + // presumably wanted things to be done in the larger chunk. + + // SAFETY: we're only ever given pointers that are valid to read/write, + // including being aligned, and nothing here panics so it's drop-safe. + unsafe { + let a: MaybeUninit = read(x); + let b: MaybeUninit = read(y); + write(x, b); + write(y, a); + } i += 1; } diff --git a/tests/ui/consts/missing_span_in_backtrace.stderr b/tests/ui/consts/missing_span_in_backtrace.stderr index 3e3e8e976be..9e0506e7e38 100644 --- a/tests/ui/consts/missing_span_in_backtrace.stderr +++ b/tests/ui/consts/missing_span_in_backtrace.stderr @@ -5,8 +5,6 @@ error[E0080]: evaluation of constant value failed | note: inside `std::ptr::read::>>` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL -note: inside `mem::swap_simple::>>` - --> $SRC_DIR/core/src/mem/mod.rs:LL:COL note: inside `std::ptr::swap_nonoverlapping_simple_untyped::>` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL note: inside `swap_nonoverlapping::>`