@@ -867,12 +867,10 @@ impl<T: ?Sized> Arc<T> {
867867 unsafe fn drop_slow ( & mut self ) {
868868 // Destroy the data at this time, even though we may not free the box
869869 // allocation itself (there may still be weak pointers lying around).
870- ptr:: drop_in_place ( & mut self . ptr . as_mut ( ) . data ) ;
870+ ptr:: drop_in_place ( Self :: get_mut_unchecked ( self ) ) ;
871871
872- if self . inner ( ) . weak . fetch_sub ( 1 , Release ) == 1 {
873- acquire ! ( self . inner( ) . weak) ;
874- Global . dealloc ( self . ptr . cast ( ) , Layout :: for_value ( self . ptr . as_ref ( ) ) )
875- }
872+ // Drop the weak ref collectively held by all strong references
873+ drop ( Weak { ptr : self . ptr } ) ;
876874 }
877875
878876 #[ inline]
@@ -1204,7 +1202,7 @@ impl<T: Clone> Arc<T> {
12041202
12051203 // As with `get_mut()`, the unsafety is ok because our reference was
12061204 // either unique to begin with, or became one upon cloning the contents.
1207- unsafe { & mut this . ptr . as_mut ( ) . data }
1205+ unsafe { Self :: get_mut_unchecked ( this ) }
12081206 }
12091207}
12101208
@@ -1280,7 +1278,9 @@ impl<T: ?Sized> Arc<T> {
12801278 #[ inline]
12811279 #[ unstable( feature = "get_mut_unchecked" , issue = "63292" ) ]
12821280 pub unsafe fn get_mut_unchecked ( this : & mut Self ) -> & mut T {
1283- & mut this. ptr . as_mut ( ) . data
1281+ // We are careful to *not* create a reference covering the "count" fields, as
1282+ // this would alias with concurrent access to the reference counts (e.g. by `Weak`).
1283+ & mut ( * this. ptr . as_ptr ( ) ) . data
12841284 }
12851285
12861286 /// Determine whether this is the unique reference (including weak refs) to
@@ -1571,6 +1571,13 @@ impl<T> Weak<T> {
15711571 }
15721572}
15731573
1574+ /// Helper type to allow accessing the reference counts without
1575+ /// making any assertions about the data field.
1576+ struct WeakInner < ' a > {
1577+ weak : & ' a atomic:: AtomicUsize ,
1578+ strong : & ' a atomic:: AtomicUsize ,
1579+ }
1580+
15741581impl < T : ?Sized > Weak < T > {
15751582 /// Attempts to upgrade the `Weak` pointer to an [`Arc`], delaying
15761583 /// dropping of the inner value if successful.
@@ -1678,8 +1685,18 @@ impl<T: ?Sized> Weak<T> {
16781685 /// Returns `None` when the pointer is dangling and there is no allocated `ArcInner`,
16791686 /// (i.e., when this `Weak` was created by `Weak::new`).
16801687 #[ inline]
1681- fn inner ( & self ) -> Option < & ArcInner < T > > {
1682- if is_dangling ( self . ptr ) { None } else { Some ( unsafe { self . ptr . as_ref ( ) } ) }
1688+ fn inner ( & self ) -> Option < WeakInner < ' _ > > {
1689+ if is_dangling ( self . ptr ) {
1690+ None
1691+ } else {
1692+ // We are careful to *not* create a reference covering the "data" field, as
1693+ // the field may be mutated concurrently (for example, if the last `Arc`
1694+ // is dropped, the data field will be dropped in-place).
1695+ Some ( unsafe {
1696+ let ptr = self . ptr . as_ptr ( ) ;
1697+ WeakInner { strong : & ( * ptr) . strong , weak : & ( * ptr) . weak }
1698+ } )
1699+ }
16831700 }
16841701
16851702 /// Returns `true` if the two `Weak`s point to the same allocation (similar to
0 commit comments