From bc0788b99b47cee916e5b06ded5a4ddbb973bd26 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Fri, 17 Jun 2022 15:01:03 +0200 Subject: [PATCH 1/3] Use mem::replace in ptr::replace instead of mem::swap --- library/core/src/ptr/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 8fb0bfbe2e31b..337c7365d2b42 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1012,16 +1012,15 @@ const unsafe fn swap_nonoverlapping_simple<T>(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<T>(dst: *mut T, mut src: T) -> T { +pub const unsafe fn replace<T>(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), // and cannot overlap `src` since `dst` must point to a distinct // allocated object. 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 From 6bf4c57f27b30ddf1cf2992e495fb8677271b57d Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Fri, 24 Jun 2022 15:14:29 +0200 Subject: [PATCH 2/3] update comment --- library/core/src/ptr/mod.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 337c7365d2b42..18978d7886469 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1013,10 +1013,9 @@ const unsafe fn swap_nonoverlapping_simple<T>(x: *mut T, y: *mut T, count: usize #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_replace", issue = "83164")] pub const unsafe fn replace<T>(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), - // and cannot overlap `src` since `dst` must point to a distinct - // allocated object. + // 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::replace(&mut *dst, src) From d8d241262d0dcb27dacdb5a589ad168c6be043a4 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Fri, 24 Jun 2022 15:37:52 +0200 Subject: [PATCH 3/3] replace mem::replace with ptr::replace if applicable --- library/std/src/thread/local.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) 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<T: 'static> LocalKey<RefCell<T>> { mod lazy { use crate::cell::UnsafeCell; use crate::hint; - use crate::mem; + use crate::ptr; pub struct LazyKeyInner<T> { inner: UnsafeCell<Option<T>>, @@ -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 {