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 {