Skip to content

Commit da1ddcf

Browse files
committed
Simplify internals of {Rc,Arc}::default
This commit simplifies the internal implementation of `Default` for these two pointer types to have the same performance characteristics as before (a side effect of changes in 131460) while avoid use of internal private APIs of Rc/Arc. To preserve the same codegen as before some non-generic functions needed to be tagged as `#[inline]` as well, but otherwise the same IR is produced before/after this change. The motivation of this commit is I was studying up on the state of initialization of `Arc` and `Rc` and figured it'd be nicer to reduce the use of internal APIs and instead use public stable APIs where possible, even in the implementation itself.
1 parent 71dc761 commit da1ddcf

File tree

2 files changed

+18
-18
lines changed

2 files changed

+18
-18
lines changed

library/alloc/src/rc.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ struct RcInner<T: ?Sized> {
289289
}
290290

291291
/// Calculate layout for `RcInner<T>` using the inner value's layout
292+
#[inline]
292293
fn rc_inner_layout_for_value_layout(layout: Layout) -> Layout {
293294
// Calculate layout using the given value layout.
294295
// Previously, layout was calculated on the expression
@@ -2518,15 +2519,16 @@ impl<T: Default> Default for Rc<T> {
25182519
/// ```
25192520
#[inline]
25202521
fn default() -> Self {
2522+
let mut rc = Rc::new_uninit();
2523+
2524+
// SAFETY: this is a freshly allocated `Rc` so it's guaranteed there are
2525+
// no other strong or weak pointers other than `rc` itself.
25212526
unsafe {
2522-
Self::from_inner(
2523-
Box::leak(Box::write(
2524-
Box::new_uninit(),
2525-
RcInner { strong: Cell::new(1), weak: Cell::new(1), value: T::default() },
2526-
))
2527-
.into(),
2528-
)
2527+
Rc::get_mut_unchecked(&mut rc).write(T::default());
25292528
}
2529+
2530+
// SAFETY: this allocation was just initialized above.
2531+
unsafe { rc.assume_init() }
25302532
}
25312533
}
25322534

library/alloc/src/sync.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@ struct ArcInner<T: ?Sized> {
392392
}
393393

394394
/// Calculate layout for `ArcInner<T>` using the inner value's layout
395+
#[inline]
395396
fn arcinner_layout_for_value_layout(layout: Layout) -> Layout {
396397
// Calculate layout using the given value layout.
397398
// Previously, layout was calculated on the expression
@@ -3724,19 +3725,16 @@ impl<T: Default> Default for Arc<T> {
37243725
/// assert_eq!(*x, 0);
37253726
/// ```
37263727
fn default() -> Arc<T> {
3728+
let mut arc = Arc::new_uninit();
3729+
3730+
// SAFETY: this is a freshly allocated `Arc` so it's guaranteed there
3731+
// are no other strong or weak pointers other than `arc` itself.
37273732
unsafe {
3728-
Self::from_inner(
3729-
Box::leak(Box::write(
3730-
Box::new_uninit(),
3731-
ArcInner {
3732-
strong: atomic::AtomicUsize::new(1),
3733-
weak: atomic::AtomicUsize::new(1),
3734-
data: T::default(),
3735-
},
3736-
))
3737-
.into(),
3738-
)
3733+
Arc::get_mut_unchecked(&mut arc).write(T::default());
37393734
}
3735+
3736+
// SAFETY: this allocation was just initialized above.
3737+
unsafe { arc.assume_init() }
37403738
}
37413739
}
37423740

0 commit comments

Comments
 (0)