From 57d20c1d14c044d96aaf914fff12e773f5f41fe8 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 25 Feb 2026 13:09:14 -0800 Subject: [PATCH] Revert "Simplify internals of `{Rc,Arc}::default`" This reverts commit ce4c17f61588ab794c966b052dbc0f69cee47e8d. --- library/alloc/src/rc.rs | 25 ++++++------------- library/alloc/src/sync.rs | 29 +++++++++-------------- tests/codegen-llvm/issues/issue-111603.rs | 12 +++++----- 3 files changed, 24 insertions(+), 42 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index f63351ebfd809..cec41524325e0 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -289,7 +289,6 @@ struct RcInner { } /// Calculate layout for `RcInner` using the inner value's layout -#[inline] fn rc_inner_layout_for_value_layout(layout: Layout) -> Layout { // Calculate layout using the given value layout. // Previously, layout was calculated on the expression @@ -2519,25 +2518,15 @@ impl Default for Rc { /// ``` #[inline] fn default() -> Self { - // First create an uninitialized allocation before creating an instance - // of `T`. This avoids having `T` on the stack and avoids the need to - // codegen a call to the destructor for `T` leading to generally better - // codegen. See #131460 for some more details. - let mut rc = Rc::new_uninit(); - - // SAFETY: this is a freshly allocated `Rc` so it's guaranteed there are - // no other strong or weak pointers other than `rc` itself. unsafe { - let raw = Rc::get_mut_unchecked(&mut rc); - - // Note that `ptr::write` here is used specifically instead of - // `MaybeUninit::write` to avoid creating an extra stack copy of `T` - // in debug mode. See #136043 for more context. - ptr::write(raw.as_mut_ptr(), T::default()); + Self::from_inner( + Box::leak(Box::write( + Box::new_uninit(), + RcInner { strong: Cell::new(1), weak: Cell::new(1), value: T::default() }, + )) + .into(), + ) } - - // SAFETY: this allocation was just initialized above. - unsafe { rc.assume_init() } } } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index d097588f8e633..dc82357dd146b 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -392,7 +392,6 @@ struct ArcInner { } /// Calculate layout for `ArcInner` using the inner value's layout -#[inline] fn arcinner_layout_for_value_layout(layout: Layout) -> Layout { // Calculate layout using the given value layout. // Previously, layout was calculated on the expression @@ -3725,25 +3724,19 @@ impl Default for Arc { /// assert_eq!(*x, 0); /// ``` fn default() -> Arc { - // First create an uninitialized allocation before creating an instance - // of `T`. This avoids having `T` on the stack and avoids the need to - // codegen a call to the destructor for `T` leading to generally better - // codegen. See #131460 for some more details. - let mut arc = Arc::new_uninit(); - - // SAFETY: this is a freshly allocated `Arc` so it's guaranteed there - // are no other strong or weak pointers other than `arc` itself. unsafe { - let raw = Arc::get_mut_unchecked(&mut arc); - - // Note that `ptr::write` here is used specifically instead of - // `MaybeUninit::write` to avoid creating an extra stack copy of `T` - // in debug mode. See #136043 for more context. - ptr::write(raw.as_mut_ptr(), T::default()); + Self::from_inner( + Box::leak(Box::write( + Box::new_uninit(), + ArcInner { + strong: atomic::AtomicUsize::new(1), + weak: atomic::AtomicUsize::new(1), + data: T::default(), + }, + )) + .into(), + ) } - - // SAFETY: this allocation was just initialized above. - unsafe { arc.assume_init() } } } diff --git a/tests/codegen-llvm/issues/issue-111603.rs b/tests/codegen-llvm/issues/issue-111603.rs index 91eb836478eb1..2ba5a3f876aed 100644 --- a/tests/codegen-llvm/issues/issue-111603.rs +++ b/tests/codegen-llvm/issues/issue-111603.rs @@ -10,9 +10,9 @@ use std::sync::Arc; pub fn new_from_array(x: u64) -> Arc<[u64]> { // Ensure that we only generate one alloca for the array. - // CHECK: %[[A:.+]] = alloca + // CHECK: alloca // CHECK-SAME: [8000 x i8] - // CHECK-NOT: %[[B:.+]] = alloca + // CHECK-NOT: alloca let array = [x; 1000]; Arc::new(array) } @@ -20,9 +20,8 @@ pub fn new_from_array(x: u64) -> Arc<[u64]> { // CHECK-LABEL: @new_uninit #[no_mangle] pub fn new_uninit(x: u64) -> Arc<[u64; 1000]> { - // CHECK: %[[A:.+]] = alloca - // CHECK-SAME: [8000 x i8] - // CHECK-NOT: %[[B:.+]] = alloca + // CHECK: call alloc::sync::arcinner_layout_for_value_layout + // CHECK-NOT: call alloc::sync::arcinner_layout_for_value_layout let mut arc = Arc::new_uninit(); unsafe { Arc::get_mut_unchecked(&mut arc) }.write([x; 1000]); unsafe { arc.assume_init() } @@ -31,7 +30,8 @@ pub fn new_uninit(x: u64) -> Arc<[u64; 1000]> { // CHECK-LABEL: @new_uninit_slice #[no_mangle] pub fn new_uninit_slice(x: u64) -> Arc<[u64]> { - // CHECK-NOT: %[[B:.+]] = alloca + // CHECK: call alloc::sync::arcinner_layout_for_value_layout + // CHECK-NOT: call alloc::sync::arcinner_layout_for_value_layout let mut arc = Arc::new_uninit_slice(1000); for elem in unsafe { Arc::get_mut_unchecked(&mut arc) } { elem.write(x);