diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 8183a582d33..b267377d90a 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -265,6 +265,7 @@ use core::slice::from_raw_parts_mut; use crate::alloc::{box_free, handle_alloc_error, AllocError, Allocator, Global, Layout}; use crate::borrow::{Cow, ToOwned}; +use crate::boxed::WriteCloneIntoRaw; use crate::string::String; use crate::vec::Vec; @@ -1037,8 +1038,14 @@ impl Rc { #[stable(feature = "rc_unique", since = "1.4.0")] pub fn make_mut(this: &mut Self) -> &mut T { if Rc::strong_count(this) != 1 { - // Gotta clone the data, there are other Rcs - *this = Rc::new((**this).clone()) + // Gotta clone the data, there are other Rcs. + // Pre-allocate memory to allow writing the cloned value directly. + let mut rc = Self::new_uninit(); + unsafe { + let data = Rc::get_mut_unchecked(&mut rc); + (**this).write_clone_into_raw(data.as_mut_ptr()); + *this = rc.assume_init(); + } } else if Rc::weak_count(this) != 0 { // Can just steal the data, all that's left is Weaks unsafe { diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 06ad6217271..deeb6941fcf 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -24,7 +24,7 @@ use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst}; use crate::alloc::{box_free, handle_alloc_error, AllocError, Allocator, Global, Layout}; use crate::borrow::{Cow, ToOwned}; -use crate::boxed::Box; +use crate::boxed::{Box, WriteCloneIntoRaw}; use crate::rc::is_dangling; use crate::string::String; use crate::vec::Vec; @@ -1369,8 +1369,14 @@ impl Arc { // weak count, there's no chance the ArcInner itself could be // deallocated. if this.inner().strong.compare_exchange(1, 0, Acquire, Relaxed).is_err() { - // Another strong pointer exists; clone - *this = Arc::new((**this).clone()); + // Another strong pointer exists, so we must clone. + // Pre-allocate memory to allow writing the cloned value directly. + let mut arc = Self::new_uninit(); + unsafe { + let data = Arc::get_mut_unchecked(&mut arc); + (**this).write_clone_into_raw(data.as_mut_ptr()); + *this = arc.assume_init(); + } } else if this.inner().weak.load(Relaxed) != 1 { // Relaxed suffices in the above because this is fundamentally an // optimization: we are always racing with weak pointers being