diff options
Diffstat (limited to 'src/liballoc/sync.rs')
| -rw-r--r-- | src/liballoc/sync.rs | 23 | 
1 files changed, 16 insertions, 7 deletions
| diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 35935861fb1..b63b3684964 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -25,7 +25,7 @@ use core::cmp::Ordering; use core::intrinsics::abort; use core::mem::{self, align_of_val, size_of_val}; use core::ops::Deref; -use core::ops::CoerceUnsized; +use core::ops::{CoerceUnsized, DispatchFromDyn}; use core::pin::Pin; use core::ptr::{self, NonNull}; use core::marker::{Unpin, Unsize, PhantomData}; @@ -199,7 +199,7 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// counting in general. /// /// [rc_examples]: ../../std/rc/index.html#examples -#[cfg_attr(all(not(stage0), not(test)), lang = "arc")] +#[cfg_attr(not(test), lang = "arc")] #[stable(feature = "rust1", since = "1.0.0")] pub struct Arc<T: ?Sized> { ptr: NonNull<ArcInner<T>>, @@ -214,6 +214,9 @@ unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {} #[unstable(feature = "coerce_unsized", issue = "27732")] impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {} +#[unstable(feature = "dispatch_from_dyn", issue = "0")] +impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Arc<U>> for Arc<T> {} + /// `Weak` is a version of [`Arc`] that holds a non-owning reference to the /// managed value. The value is accessed by calling [`upgrade`] on the `Weak` /// pointer, which returns an [`Option`]`<`[`Arc`]`<T>>`. @@ -254,6 +257,8 @@ unsafe impl<T: ?Sized + Sync + Send> Sync for Weak<T> {} #[unstable(feature = "coerce_unsized", issue = "27732")] impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {} +#[unstable(feature = "dispatch_from_dyn", issue = "0")] +impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Weak<U>> for Weak<T> {} #[stable(feature = "arc_weak", since = "1.4.0")] impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> { @@ -566,16 +571,20 @@ impl<T: ?Sized> Arc<T> { impl<T: ?Sized> Arc<T> { // Allocates an `ArcInner<T>` with sufficient space for an unsized value unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner<T> { - // Create a fake ArcInner to find allocation size and alignment - let fake_ptr = ptr as *mut ArcInner<T>; - - let layout = Layout::for_value(&*fake_ptr); + // Calculate layout using the given value. + // Previously, layout was calculated on the expression + // `&*(ptr as *const ArcInner<T>)`, but this created a misaligned + // reference (see #54908). + let layout = Layout::new::<ArcInner<()>>() + .extend(Layout::for_value(&*ptr)).unwrap().0 + .pad_to_align().unwrap(); let mem = Global.alloc(layout) .unwrap_or_else(|_| handle_alloc_error(layout)); - // Initialize the real ArcInner + // Initialize the ArcInner let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut ArcInner<T>; + debug_assert_eq!(Layout::for_value(&*inner), layout); ptr::write(&mut (*inner).strong, atomic::AtomicUsize::new(1)); ptr::write(&mut (*inner).weak, atomic::AtomicUsize::new(1)); | 
