diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 8fb0bfbe2e31b..18978d7886469 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1012,16 +1012,14 @@ const unsafe fn swap_nonoverlapping_simple(x: *mut T, y: *mut T, count: usize #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_replace", issue = "83164")] -pub const unsafe fn replace(dst: *mut T, mut src: T) -> T { - // SAFETY: the caller must guarantee that `dst` is valid to be - // cast to a mutable reference (valid for writes, aligned, initialized), - // and cannot overlap `src` since `dst` must point to a distinct - // allocated object. +pub const unsafe fn replace(dst: *mut T, src: T) -> T { + // SAFETY: The caller must guarantee that `dst` is valid to be + // cast to a mutable reference (valid for writes, aligned, initialized). + // `dst` cannot overlap `src` since `src` is a freshly stack-allocated local variable. unsafe { assert_unsafe_precondition!(is_aligned_and_not_null(dst)); - mem::swap(&mut *dst, &mut src); // cannot overlap + mem::replace(&mut *dst, src) } - src } /// Reads the value from `src` without moving it. This leaves the diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index f4750cdf764dc..cfb824bf3b6f5 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -782,7 +782,7 @@ impl LocalKey> { mod lazy { use crate::cell::UnsafeCell; use crate::hint; - use crate::mem; + use crate::ptr; pub struct LazyKeyInner { inner: UnsafeCell>, @@ -811,7 +811,7 @@ mod lazy { // SAFETY: // - // note that this can in theory just be `*ptr = Some(value)`, but due to + // Note that this can in theory just be `*ptr = Some(value)`, but due to // the compiler will currently codegen that pattern with something like: // // ptr::drop_in_place(ptr) @@ -821,16 +821,20 @@ mod lazy { // `ptr` (e.g., if this is being recursively initialized) to re-access // TLS, in which case there will be a `&` and `&mut` pointer to the same // value (an aliasing violation). To avoid setting the "I'm running a - // destructor" flag we just use `mem::replace` which should sequence the - // operations a little differently and make this safe to call. + // destructor" flag we just use `ptr::replace` which should sequence the + // operations a little differently and make this safe to call: + // + // let tmp = ptr::read(ptr) + // ptr::write(ptr, Some(value)) + // drop(tmp) // // The precondition also ensures that we are the only one accessing // `self` at the moment so replacing is fine. unsafe { - let _ = mem::replace(&mut *ptr, Some(value)); + let _ = ptr::replace(ptr, Some(value)); } - // SAFETY: With the call to `mem::replace` it is guaranteed there is + // SAFETY: With the call to `ptr::replace` it is guaranteed there is // a `Some` behind `ptr`, not a `None` so `unreachable_unchecked` // will never be reached. unsafe {