@@ -867,12 +867,10 @@ impl<T: ?Sized> Arc<T> {
867
867
unsafe fn drop_slow ( & mut self ) {
868
868
// Destroy the data at this time, even though we may not free the box
869
869
// 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 ) ) ;
871
871
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 } ) ;
876
874
}
877
875
878
876
#[ inline]
@@ -1204,7 +1202,7 @@ impl<T: Clone> Arc<T> {
1204
1202
1205
1203
// As with `get_mut()`, the unsafety is ok because our reference was
1206
1204
// 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 ) }
1208
1206
}
1209
1207
}
1210
1208
@@ -1280,7 +1278,9 @@ impl<T: ?Sized> Arc<T> {
1280
1278
#[ inline]
1281
1279
#[ unstable( feature = "get_mut_unchecked" , issue = "63292" ) ]
1282
1280
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
1284
1284
}
1285
1285
1286
1286
/// Determine whether this is the unique reference (including weak refs) to
@@ -1571,6 +1571,13 @@ impl<T> Weak<T> {
1571
1571
}
1572
1572
}
1573
1573
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
+
1574
1581
impl < T : ?Sized > Weak < T > {
1575
1582
/// Attempts to upgrade the `Weak` pointer to an [`Arc`], delaying
1576
1583
/// dropping of the inner value if successful.
@@ -1678,8 +1685,18 @@ impl<T: ?Sized> Weak<T> {
1678
1685
/// Returns `None` when the pointer is dangling and there is no allocated `ArcInner`,
1679
1686
/// (i.e., when this `Weak` was created by `Weak::new`).
1680
1687
#[ 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
+ }
1683
1700
}
1684
1701
1685
1702
/// Returns `true` if the two `Weak`s point to the same allocation (similar to
0 commit comments