From 5c6326ad799511e59b1de60b25603309d5322090 Mon Sep 17 00:00:00 2001 From: Billy Sheppard Date: Fri, 3 May 2024 00:10:40 +0000 Subject: [PATCH 1/3] added Default impls reorganised attrs removed OsStr impls added backticks --- library/alloc/src/ffi/c_str.rs | 22 ++++++++++++++++++++++ library/alloc/src/rc.rs | 21 +++++++++++++++++++++ library/alloc/src/sync.rs | 21 +++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index f143e557871..19dd90eb81f 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -910,6 +910,28 @@ impl From<&CStr> for Rc { } } +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")] +impl Default for Arc { + /// Creates an empty CStr inside an Arc + #[inline] + fn default() -> Self { + let c_str: &CStr = Default::default(); + Arc::from(c_str) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")] +impl Default for Rc { + /// Creates an empty CStr inside an Rc + #[inline] + fn default() -> Self { + let c_str: &CStr = Default::default(); + Rc::from(c_str) + } +} + #[cfg(not(test))] #[stable(feature = "default_box_extra", since = "1.17.0")] impl Default for Box { diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 45b20535675..206489876e3 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2224,6 +2224,27 @@ impl Default for Rc { } } +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")] +impl Default for Rc { + /// Creates an empty str inside an Rc + #[inline] + fn default() -> Self { + Rc::from("") + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")] +impl Default for Rc<[T]> { + /// Creates an empty `[T]` inside an Rc + #[inline] + fn default() -> Self { + let arr: [T; 0] = []; + Rc::from(arr) + } +} + #[stable(feature = "rust1", since = "1.0.0")] trait RcEqIdent { fn eq(&self, other: &Rc) -> bool; diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index a35c99849b3..5f6ce80e194 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -3300,6 +3300,27 @@ impl Default for Arc { } } +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")] +impl Default for Arc { + /// Creates an empty str inside an Arc + #[inline] + fn default() -> Self { + Arc::from("") + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")] +impl Default for Arc<[T]> { + /// Creates an empty `[T]` inside an Arc + #[inline] + fn default() -> Self { + let arr: [T; 0] = []; + Arc::from(arr) + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Hash for Arc { fn hash(&self, state: &mut H) { From 0b3ebb546fac5de6be624d335abb3c5f7ad82c74 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Sat, 11 May 2024 07:11:36 -0500 Subject: [PATCH 2/3] Add note about possible allocation-sharing to Arc/Rc::default. --- library/alloc/src/ffi/c_str.rs | 4 ++++ library/alloc/src/rc.rs | 4 ++++ library/alloc/src/sync.rs | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index 19dd90eb81f..3b56a5717e2 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -914,6 +914,8 @@ impl From<&CStr> for Rc { #[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")] impl Default for Arc { /// Creates an empty CStr inside an Arc + /// + /// This may or may not share an allocation with other Arcs. #[inline] fn default() -> Self { let c_str: &CStr = Default::default(); @@ -925,6 +927,8 @@ impl Default for Arc { #[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")] impl Default for Rc { /// Creates an empty CStr inside an Rc + /// + /// This may or may not share an allocation with other Rcs on the same thread. #[inline] fn default() -> Self { let c_str: &CStr = Default::default(); diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 206489876e3..dddd0603a15 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2228,6 +2228,8 @@ impl Default for Rc { #[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")] impl Default for Rc { /// Creates an empty str inside an Rc + /// + /// This may or may not share an allocation with other Rcs on the same thread. #[inline] fn default() -> Self { Rc::from("") @@ -2238,6 +2240,8 @@ impl Default for Rc { #[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")] impl Default for Rc<[T]> { /// Creates an empty `[T]` inside an Rc + /// + /// This may or may not share an allocation with other Rcs on the same thread. #[inline] fn default() -> Self { let arr: [T; 0] = []; diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 5f6ce80e194..f06994f7c40 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -3304,6 +3304,8 @@ impl Default for Arc { #[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")] impl Default for Arc { /// Creates an empty str inside an Arc + /// + /// This may or may not share an allocation with other Arcs. #[inline] fn default() -> Self { Arc::from("") @@ -3314,6 +3316,8 @@ impl Default for Arc { #[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")] impl Default for Arc<[T]> { /// Creates an empty `[T]` inside an Arc + /// + /// This may or may not share an allocation with other Arcs. #[inline] fn default() -> Self { let arr: [T; 0] = []; From f27d1e114c70ff4aca98f3afc2d432b1169b3465 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Sat, 11 May 2024 09:54:32 -0500 Subject: [PATCH 3/3] Use shared statics for the ArcInner for Arc::default, and for Arc<[T]>::default where alignof(T) <= 16. --- library/alloc/src/ffi/c_str.rs | 13 --------- library/alloc/src/sync.rs | 52 +++++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 14 deletions(-) diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index 3b56a5717e2..b13af93d06c 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -910,19 +910,6 @@ impl From<&CStr> for Rc { } } -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")] -impl Default for Arc { - /// Creates an empty CStr inside an Arc - /// - /// This may or may not share an allocation with other Arcs. - #[inline] - fn default() -> Self { - let c_str: &CStr = Default::default(); - Arc::from(c_str) - } -} - #[cfg(not(no_global_oom_handling))] #[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")] impl Default for Rc { diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index f06994f7c40..a925b544bc2 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -3308,7 +3308,32 @@ impl Default for Arc { /// This may or may not share an allocation with other Arcs. #[inline] fn default() -> Self { - Arc::from("") + let arc: Arc<[u8]> = Default::default(); + debug_assert!(core::str::from_utf8(&*arc).is_ok()); + let (ptr, alloc) = Arc::into_inner_with_allocator(arc); + unsafe { Arc::from_ptr_in(ptr.as_ptr() as *mut ArcInner, alloc) } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")] +impl Default for Arc { + /// Creates an empty CStr inside an Arc + /// + /// This may or may not share an allocation with other Arcs. + #[inline] + fn default() -> Self { + use core::ffi::CStr; + static STATIC_INNER_CSTR: ArcInner<[u8; 1]> = ArcInner { + strong: atomic::AtomicUsize::new(1), + weak: atomic::AtomicUsize::new(1), + data: [0], + }; + let inner: NonNull> = NonNull::from(&STATIC_INNER_CSTR); + let inner: NonNull> = NonNull::new(inner.as_ptr() as *mut ArcInner).unwrap(); + // `this` semantically is the Arc "owned" by the static, so make sure not to drop it. + let this: mem::ManuallyDrop> = unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) }; + (*this).clone() } } @@ -3320,6 +3345,31 @@ impl Default for Arc<[T]> { /// This may or may not share an allocation with other Arcs. #[inline] fn default() -> Self { + let alignment_of_t: usize = mem::align_of::(); + // We only make statics for the lowest five alignments. + // Alignments greater than that will use dynamic allocation. + macro_rules! use_static_inner_for_alignments { + ($($alignment:literal),*) => { + $(if alignment_of_t == $alignment { + // Note: this must be in a new scope because static and type names are unhygenic. + #[repr(align($alignment))] + struct Aligned; + static ALIGNED_STATIC_INNER: ArcInner = ArcInner { + strong: atomic::AtomicUsize::new(1), + weak: atomic::AtomicUsize::new(1), + data: Aligned, + }; + let inner: NonNull> = NonNull::from(&ALIGNED_STATIC_INNER); + let inner: NonNull> = inner.cast(); + // `this` semantically is the Arc "owned" by the static, so make sure not to drop it. + let this: mem::ManuallyDrop> = unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) }; + return (*this).clone(); + })* + }; + } + use_static_inner_for_alignments!(1, 2, 4, 8, 16); + + // If T's alignment is not one of the ones we have a static for, make a new unique allocation. let arr: [T; 0] = []; Arc::from(arr) }