@@ -866,12 +866,10 @@ impl<T: ?Sized> Arc<T> {
866
866
unsafe fn drop_slow ( & mut self ) {
867
867
// Destroy the data at this time, even though we may not free the box
868
868
// 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 ) ) ;
870
870
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 } ) ;
875
873
}
876
874
877
875
#[ inline]
@@ -1201,7 +1199,7 @@ impl<T: Clone> Arc<T> {
1201
1199
1202
1200
// As with `get_mut()`, the unsafety is ok because our reference was
1203
1201
// 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 ) }
1205
1203
}
1206
1204
}
1207
1205
@@ -1277,7 +1275,9 @@ impl<T: ?Sized> Arc<T> {
1277
1275
#[ inline]
1278
1276
#[ unstable( feature = "get_mut_unchecked" , issue = "63292" ) ]
1279
1277
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
1281
1281
}
1282
1282
1283
1283
/// Determine whether this is the unique reference (including weak refs) to
@@ -1568,6 +1568,13 @@ impl<T> Weak<T> {
1568
1568
}
1569
1569
}
1570
1570
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
+
1571
1578
impl < T : ?Sized > Weak < T > {
1572
1579
/// Attempts to upgrade the `Weak` pointer to an [`Arc`], delaying
1573
1580
/// dropping of the inner value if successful.
@@ -1673,8 +1680,18 @@ impl<T: ?Sized> Weak<T> {
1673
1680
/// Returns `None` when the pointer is dangling and there is no allocated `ArcInner`,
1674
1681
/// (i.e., when this `Weak` was created by `Weak::new`).
1675
1682
#[ 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
+ }
1678
1695
}
1679
1696
1680
1697
/// Returns `true` if the two `Weak`s point to the same allocation (similar to
0 commit comments