Auto merge of #124640 - Billy-Sheppard:master, r=dtolnay
Fix #124275: Implemented Default for `Arc<str>` With added implementations. ``` GOOD Arc<CStr> BROKEN Arc<OsStr> // removed GOOD Rc<str> GOOD Rc<CStr> BROKEN Rc<OsStr> // removed GOOD Rc<[T]> GOOD Arc<[T]> ``` For discussion of https://github.com/rust-lang/rust/pull/124367#issuecomment-2091940137. Key pain points currently: > I've had a guess at the best locations/feature attrs for them but they might not be correct. > However I'm unclear how to get the OsStr impl to compile, which file should they go in to avoid the error below? Is it possible, perhaps with some special std rust lib magic?
This commit is contained in:
commit
496f7310c8
@ -910,6 +910,19 @@ fn from(s: &CStr) -> Rc<CStr> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl Default for Rc<CStr> {
|
||||
/// 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();
|
||||
Rc::from(c_str)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[stable(feature = "default_box_extra", since = "1.17.0")]
|
||||
impl Default for Box<CStr> {
|
||||
|
@ -2224,6 +2224,31 @@ fn default() -> Rc<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl Default for Rc<str> {
|
||||
/// 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("")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T> 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] = [];
|
||||
Rc::from(arr)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
trait RcEqIdent<T: ?Sized + PartialEq, A: Allocator> {
|
||||
fn eq(&self, other: &Rc<T, A>) -> bool;
|
||||
|
@ -3300,6 +3300,81 @@ fn default() -> Arc<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl Default for Arc<str> {
|
||||
/// Creates an empty str inside an Arc
|
||||
///
|
||||
/// This may or may not share an allocation with other Arcs.
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
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<str>, alloc) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl Default for Arc<core::ffi::CStr> {
|
||||
/// 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<ArcInner<[u8]>> = NonNull::from(&STATIC_INNER_CSTR);
|
||||
let inner: NonNull<ArcInner<CStr>> = NonNull::new(inner.as_ptr() as *mut ArcInner<CStr>).unwrap();
|
||||
// `this` semantically is the Arc "owned" by the static, so make sure not to drop it.
|
||||
let this: mem::ManuallyDrop<Arc<CStr>> = unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) };
|
||||
(*this).clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T> 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 alignment_of_t: usize = mem::align_of::<T>();
|
||||
// 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<Aligned> = ArcInner {
|
||||
strong: atomic::AtomicUsize::new(1),
|
||||
weak: atomic::AtomicUsize::new(1),
|
||||
data: Aligned,
|
||||
};
|
||||
let inner: NonNull<ArcInner<Aligned>> = NonNull::from(&ALIGNED_STATIC_INNER);
|
||||
let inner: NonNull<ArcInner<[T; 0]>> = inner.cast();
|
||||
// `this` semantically is the Arc "owned" by the static, so make sure not to drop it.
|
||||
let this: mem::ManuallyDrop<Arc<[T; 0]>> = 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)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized + Hash, A: Allocator> Hash for Arc<T, A> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
|
Loading…
Reference in New Issue
Block a user