Skip to content

Commit cc1bd5b

Browse files
added Default impls
reorganised attrs removed OsStr impls added backticks Add note about possible allocation-sharing to Arc/Rc<str/[T]/CStr>::default. Use shared statics for the ArcInner for Arc<str, CStr>::default, and for Arc<[T]>::default where alignof(T) <= 16. fixed unsafe block Revert "fixed unsafe block"
1 parent ecbe3fd commit cc1bd5b

File tree

3 files changed

+113
-0
lines changed

3 files changed

+113
-0
lines changed

library/alloc/src/ffi/c_str.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -910,6 +910,19 @@ impl From<&CStr> for Rc<CStr> {
910910
}
911911
}
912912

913+
#[cfg(not(no_global_oom_handling))]
914+
#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")]
915+
impl Default for Rc<CStr> {
916+
/// Creates an empty CStr inside an Rc
917+
///
918+
/// This may or may not share an allocation with other Rcs on the same thread.
919+
#[inline]
920+
fn default() -> Self {
921+
let c_str: &CStr = Default::default();
922+
Rc::from(c_str)
923+
}
924+
}
925+
913926
#[cfg(not(test))]
914927
#[stable(feature = "default_box_extra", since = "1.17.0")]
915928
impl Default for Box<CStr> {

library/alloc/src/rc.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2224,6 +2224,31 @@ impl<T: Default> Default for Rc<T> {
22242224
}
22252225
}
22262226

2227+
#[cfg(not(no_global_oom_handling))]
2228+
#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")]
2229+
impl Default for Rc<str> {
2230+
/// Creates an empty str inside an Rc
2231+
///
2232+
/// This may or may not share an allocation with other Rcs on the same thread.
2233+
#[inline]
2234+
fn default() -> Self {
2235+
Rc::from("")
2236+
}
2237+
}
2238+
2239+
#[cfg(not(no_global_oom_handling))]
2240+
#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")]
2241+
impl<T> Default for Rc<[T]> {
2242+
/// Creates an empty `[T]` inside an Rc
2243+
///
2244+
/// This may or may not share an allocation with other Rcs on the same thread.
2245+
#[inline]
2246+
fn default() -> Self {
2247+
let arr: [T; 0] = [];
2248+
Rc::from(arr)
2249+
}
2250+
}
2251+
22272252
#[stable(feature = "rust1", since = "1.0.0")]
22282253
trait RcEqIdent<T: ?Sized + PartialEq, A: Allocator> {
22292254
fn eq(&self, other: &Rc<T, A>) -> bool;

library/alloc/src/sync.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3300,6 +3300,81 @@ impl<T: Default> Default for Arc<T> {
33003300
}
33013301
}
33023302

3303+
#[cfg(not(no_global_oom_handling))]
3304+
#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")]
3305+
impl Default for Arc<str> {
3306+
/// Creates an empty str inside an Arc
3307+
///
3308+
/// This may or may not share an allocation with other Arcs.
3309+
#[inline]
3310+
fn default() -> Self {
3311+
let arc: Arc<[u8]> = Default::default();
3312+
debug_assert!(core::str::from_utf8(&*arc).is_ok());
3313+
let (ptr, alloc) = Arc::into_inner_with_allocator(arc);
3314+
unsafe { Arc::from_ptr_in(ptr.as_ptr() as *mut ArcInner<str>, alloc) }
3315+
}
3316+
}
3317+
3318+
#[cfg(not(no_global_oom_handling))]
3319+
#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")]
3320+
impl Default for Arc<core::ffi::CStr> {
3321+
/// Creates an empty CStr inside an Arc
3322+
///
3323+
/// This may or may not share an allocation with other Arcs.
3324+
#[inline]
3325+
fn default() -> Self {
3326+
use core::ffi::CStr;
3327+
static STATIC_INNER_CSTR: ArcInner<[u8; 1]> = ArcInner {
3328+
strong: atomic::AtomicUsize::new(1),
3329+
weak: atomic::AtomicUsize::new(1),
3330+
data: [0],
3331+
};
3332+
let inner: NonNull<ArcInner<[u8]>> = NonNull::from(&STATIC_INNER_CSTR);
3333+
let inner: NonNull<ArcInner<CStr>> = NonNull::new(inner.as_ptr() as *mut ArcInner<CStr>).unwrap();
3334+
// `this` semantically is the Arc "owned" by the static, so make sure not to drop it.
3335+
let this: mem::ManuallyDrop<Arc<CStr>> = unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) };
3336+
(*this).clone()
3337+
}
3338+
}
3339+
3340+
#[cfg(not(no_global_oom_handling))]
3341+
#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")]
3342+
impl<T> Default for Arc<[T]> {
3343+
/// Creates an empty `[T]` inside an Arc
3344+
///
3345+
/// This may or may not share an allocation with other Arcs.
3346+
#[inline]
3347+
fn default() -> Self {
3348+
let alignment_of_t: usize = mem::align_of::<T>();
3349+
// We only make statics for the lowest five alignments.
3350+
// Alignments greater than that will use dynamic allocation.
3351+
macro_rules! use_static_inner_for_alignments {
3352+
($($alignment:literal),*) => {
3353+
$(if alignment_of_t == $alignment {
3354+
// Note: this must be in a new scope because static and type names are unhygenic.
3355+
#[repr(align($alignment))]
3356+
struct Aligned;
3357+
static ALIGNED_STATIC_INNER: ArcInner<Aligned> = ArcInner {
3358+
strong: atomic::AtomicUsize::new(1),
3359+
weak: atomic::AtomicUsize::new(1),
3360+
data: Aligned,
3361+
};
3362+
let inner: NonNull<ArcInner<Aligned>> = NonNull::from(&ALIGNED_STATIC_INNER);
3363+
let inner: NonNull<ArcInner<[T; 0]>> = inner.cast();
3364+
// `this` semantically is the Arc "owned" by the static, so make sure not to drop it.
3365+
let this: mem::ManuallyDrop<Arc<[T; 0]>> = unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) };
3366+
return (*this).clone();
3367+
})*
3368+
};
3369+
}
3370+
use_static_inner_for_alignments!(1, 2, 4, 8, 16);
3371+
3372+
// If T's alignment is not one of the ones we have a static for, make a new unique allocation.
3373+
let arr: [T; 0] = [];
3374+
Arc::from(arr)
3375+
}
3376+
}
3377+
33033378
#[stable(feature = "rust1", since = "1.0.0")]
33043379
impl<T: ?Sized + Hash, A: Allocator> Hash for Arc<T, A> {
33053380
fn hash<H: Hasher>(&self, state: &mut H) {

0 commit comments

Comments
 (0)