@@ -866,12 +866,10 @@ impl<T: ?Sized> Arc<T> {
866866 unsafe fn drop_slow ( & mut self ) {
867867 // Destroy the data at this time, even though we may not free the box
868868 // allocation itself (there may still be weak pointers lying around).
869- ptr:: drop_in_place ( & mut self . ptr . as_mut ( ) . data ) ;
869+ ptr:: drop_in_place ( Self :: get_mut_unchecked ( self ) ) ;
870870
871- if self . inner ( ) . weak . fetch_sub ( 1 , Release ) == 1 {
872- acquire ! ( self . inner( ) . weak) ;
873- Global . dealloc ( self . ptr . cast ( ) , Layout :: for_value ( self . ptr . as_ref ( ) ) )
874- }
871+ // Drop the weak ref collectively held by all strong references
872+ drop ( Weak { ptr : self . ptr } ) ;
875873 }
876874
877875 #[ inline]
@@ -1201,7 +1199,7 @@ impl<T: Clone> Arc<T> {
12011199
12021200 // As with `get_mut()`, the unsafety is ok because our reference was
12031201 // either unique to begin with, or became one upon cloning the contents.
1204- unsafe { & mut this . ptr . as_mut ( ) . data }
1202+ unsafe { Self :: get_mut_unchecked ( this ) }
12051203 }
12061204}
12071205
@@ -1277,7 +1275,9 @@ impl<T: ?Sized> Arc<T> {
12771275 #[ inline]
12781276 #[ unstable( feature = "get_mut_unchecked" , issue = "63292" ) ]
12791277 pub unsafe fn get_mut_unchecked ( this : & mut Self ) -> & mut T {
1280- & mut this. ptr . as_mut ( ) . data
1278+ // We are careful to *not* create a reference covering the "count" fields, as
1279+ // this would alias with concurrent access to the reference counts (e.g. by `Weak`).
1280+ & mut ( * this. ptr . as_ptr ( ) ) . data
12811281 }
12821282
12831283 /// Determine whether this is the unique reference (including weak refs) to
@@ -1568,6 +1568,13 @@ impl<T> Weak<T> {
15681568 }
15691569}
15701570
1571+ /// Helper type to allow accessing the reference counts without
1572+ /// making any assertions about the data field.
1573+ struct WeakInner < ' a > {
1574+ weak : & ' a atomic:: AtomicUsize ,
1575+ strong : & ' a atomic:: AtomicUsize ,
1576+ }
1577+
15711578impl < T : ?Sized > Weak < T > {
15721579 /// Attempts to upgrade the `Weak` pointer to an [`Arc`], delaying
15731580 /// dropping of the inner value if successful.
@@ -1673,8 +1680,18 @@ impl<T: ?Sized> Weak<T> {
16731680 /// Returns `None` when the pointer is dangling and there is no allocated `ArcInner`,
16741681 /// (i.e., when this `Weak` was created by `Weak::new`).
16751682 #[ inline]
1676- fn inner ( & self ) -> Option < & ArcInner < T > > {
1677- if is_dangling ( self . ptr ) { None } else { Some ( unsafe { self . ptr . as_ref ( ) } ) }
1683+ fn inner ( & self ) -> Option < WeakInner < ' _ > > {
1684+ if is_dangling ( self . ptr ) {
1685+ None
1686+ } else {
1687+ // We are careful to *not* create a reference covering the "data" field, as
1688+ // the field may be mutated concurrently (for example, if the last `Arc`
1689+ // is dropped, the data field will be dropped in-place).
1690+ Some ( unsafe {
1691+ let ptr = self . ptr . as_ptr ( ) ;
1692+ WeakInner { strong : & ( * ptr) . strong , weak : & ( * ptr) . weak }
1693+ } )
1694+ }
16781695 }
16791696
16801697 /// Returns `true` if the two `Weak`s point to the same allocation (similar to
0 commit comments