@@ -295,6 +295,13 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Rc<U>> for Rc<T> {}
295
295
impl < T : ?Sized + Unsize < U > , U : ?Sized > DispatchFromDyn < Rc < U > > for Rc < T > { }
296
296
297
297
impl < T : ?Sized > Rc < T > {
298
+ #[ inline( always) ]
299
+ fn inner ( & self ) -> & RcBox < T > {
300
+ // This unsafety is ok because while this Rc is alive we're guaranteed
301
+ // that the inner pointer is valid.
302
+ unsafe { self . ptr . as_ref ( ) }
303
+ }
304
+
298
305
fn from_inner ( ptr : NonNull < RcBox < T > > ) -> Self {
299
306
Self { ptr, phantom : PhantomData }
300
307
}
@@ -469,7 +476,7 @@ impl<T> Rc<T> {
469
476
// the strong count, and then remove the implicit "strong weak"
470
477
// pointer while also handling drop logic by just crafting a
471
478
// fake Weak.
472
- this. dec_strong ( ) ;
479
+ this. inner ( ) . dec_strong ( ) ;
473
480
let _weak = Weak { ptr : this. ptr } ;
474
481
forget ( this) ;
475
482
Ok ( val)
@@ -735,7 +742,7 @@ impl<T: ?Sized> Rc<T> {
735
742
/// ```
736
743
#[ stable( feature = "rc_weak" , since = "1.4.0" ) ]
737
744
pub fn downgrade ( this : & Self ) -> Weak < T > {
738
- this. inc_weak ( ) ;
745
+ this. inner ( ) . inc_weak ( ) ;
739
746
// Make sure we do not create a dangling Weak
740
747
debug_assert ! ( !is_dangling( this. ptr) ) ;
741
748
Weak { ptr : this. ptr }
@@ -756,7 +763,7 @@ impl<T: ?Sized> Rc<T> {
756
763
#[ inline]
757
764
#[ stable( feature = "rc_counts" , since = "1.15.0" ) ]
758
765
pub fn weak_count ( this : & Self ) -> usize {
759
- this. weak ( ) - 1
766
+ this. inner ( ) . weak ( ) - 1
760
767
}
761
768
762
769
/// Gets the number of strong (`Rc`) pointers to this allocation.
@@ -774,7 +781,7 @@ impl<T: ?Sized> Rc<T> {
774
781
#[ inline]
775
782
#[ stable( feature = "rc_counts" , since = "1.15.0" ) ]
776
783
pub fn strong_count ( this : & Self ) -> usize {
777
- this. strong ( )
784
+ this. inner ( ) . strong ( )
778
785
}
779
786
780
787
/// Returns `true` if there are no other `Rc` or [`Weak`] pointers to
@@ -844,7 +851,9 @@ impl<T: ?Sized> Rc<T> {
844
851
#[ inline]
845
852
#[ unstable( feature = "get_mut_unchecked" , issue = "63292" ) ]
846
853
pub unsafe fn get_mut_unchecked ( this : & mut Self ) -> & mut T {
847
- unsafe { & mut this. ptr . as_mut ( ) . value }
854
+ // We are careful to *not* create a reference covering the "count" fields, as
855
+ // this would conflict with accesses to the reference counts (e.g. by `Weak`).
856
+ unsafe { & mut ( * this. ptr . as_ptr ( ) ) . value }
848
857
}
849
858
850
859
#[ inline]
@@ -931,10 +940,10 @@ impl<T: Clone> Rc<T> {
931
940
unsafe {
932
941
let mut swap = Rc :: new ( ptr:: read ( & this. ptr . as_ref ( ) . value ) ) ;
933
942
mem:: swap ( this, & mut swap) ;
934
- swap. dec_strong ( ) ;
943
+ swap. inner ( ) . dec_strong ( ) ;
935
944
// Remove implicit strong-weak ref (no need to craft a fake
936
945
// Weak here -- we know other Weaks can clean up for us)
937
- swap. dec_weak ( ) ;
946
+ swap. inner ( ) . dec_weak ( ) ;
938
947
forget ( swap) ;
939
948
}
940
949
}
@@ -1192,16 +1201,16 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc<T> {
1192
1201
/// ```
1193
1202
fn drop ( & mut self ) {
1194
1203
unsafe {
1195
- self . dec_strong ( ) ;
1196
- if self . strong ( ) == 0 {
1204
+ self . inner ( ) . dec_strong ( ) ;
1205
+ if self . inner ( ) . strong ( ) == 0 {
1197
1206
// destroy the contained object
1198
- ptr:: drop_in_place ( self . ptr . as_mut ( ) ) ;
1207
+ ptr:: drop_in_place ( Self :: get_mut_unchecked ( self ) ) ;
1199
1208
1200
1209
// remove the implicit "strong weak" pointer now that we've
1201
1210
// destroyed the contents.
1202
- self . dec_weak ( ) ;
1211
+ self . inner ( ) . dec_weak ( ) ;
1203
1212
1204
- if self . weak ( ) == 0 {
1213
+ if self . inner ( ) . weak ( ) == 0 {
1205
1214
Global . dealloc ( self . ptr . cast ( ) , Layout :: for_value ( self . ptr . as_ref ( ) ) ) ;
1206
1215
}
1207
1216
}
@@ -1227,7 +1236,7 @@ impl<T: ?Sized> Clone for Rc<T> {
1227
1236
/// ```
1228
1237
#[ inline]
1229
1238
fn clone ( & self ) -> Rc < T > {
1230
- self . inc_strong ( ) ;
1239
+ self . inner ( ) . inc_strong ( ) ;
1231
1240
Self :: from_inner ( self . ptr )
1232
1241
}
1233
1242
}
@@ -1851,6 +1860,13 @@ pub(crate) fn is_dangling<T: ?Sized>(ptr: NonNull<T>) -> bool {
1851
1860
address == usize:: MAX
1852
1861
}
1853
1862
1863
+ /// Helper type to allow accessing the reference counts without
1864
+ /// making any assertions about the data field.
1865
+ struct WeakInner < ' a > {
1866
+ weak : & ' a Cell < usize > ,
1867
+ strong : & ' a Cell < usize > ,
1868
+ }
1869
+
1854
1870
impl < T : ?Sized > Weak < T > {
1855
1871
/// Attempts to upgrade the `Weak` pointer to an [`Rc`], delaying
1856
1872
/// dropping of the inner value if successful.
@@ -1910,11 +1926,21 @@ impl<T: ?Sized> Weak<T> {
1910
1926
. unwrap_or ( 0 )
1911
1927
}
1912
1928
1913
- /// Returns `None` when the pointer is dangling and there is no allocated `RcBox`
1929
+ /// Returns `None` when the pointer is dangling and there is no allocated `RcBox`,
1914
1930
/// (i.e., when this `Weak` was created by `Weak::new`).
1915
1931
#[ inline]
1916
- fn inner ( & self ) -> Option < & RcBox < T > > {
1917
- if is_dangling ( self . ptr ) { None } else { Some ( unsafe { self . ptr . as_ref ( ) } ) }
1932
+ fn inner ( & self ) -> Option < WeakInner < ' _ > > {
1933
+ if is_dangling ( self . ptr ) {
1934
+ None
1935
+ } else {
1936
+ // We are careful to *not* create a reference covering the "data" field, as
1937
+ // the field may be mutated concurrently (for example, if the last `Rc`
1938
+ // is dropped, the data field will be dropped in-place).
1939
+ Some ( unsafe {
1940
+ let ptr = self . ptr . as_ptr ( ) ;
1941
+ WeakInner { strong : & ( * ptr) . strong , weak : & ( * ptr) . weak }
1942
+ } )
1943
+ }
1918
1944
}
1919
1945
1920
1946
/// Returns `true` if the two `Weak`s point to the same allocation (similar to
@@ -1992,14 +2018,14 @@ impl<T: ?Sized> Drop for Weak<T> {
1992
2018
/// assert!(other_weak_foo.upgrade().is_none());
1993
2019
/// ```
1994
2020
fn drop ( & mut self ) {
1995
- if let Some ( inner) = self . inner ( ) {
1996
- inner . dec_weak ( ) ;
1997
- // the weak count starts at 1, and will only go to zero if all
1998
- // the strong pointers have disappeared.
1999
- if inner . weak ( ) == 0 {
2000
- unsafe {
2001
- Global . dealloc ( self . ptr . cast ( ) , Layout :: for_value ( self . ptr . as_ref ( ) ) ) ;
2002
- }
2021
+ let inner = if let Some ( inner) = self . inner ( ) { inner } else { return } ;
2022
+
2023
+ inner . dec_weak ( ) ;
2024
+ // the weak count starts at 1, and will only go to zero if all
2025
+ // the strong pointers have disappeared.
2026
+ if inner . weak ( ) == 0 {
2027
+ unsafe {
2028
+ Global . dealloc ( self . ptr . cast ( ) , Layout :: for_value ( self . ptr . as_ref ( ) ) ) ;
2003
2029
}
2004
2030
}
2005
2031
}
@@ -2065,12 +2091,13 @@ impl<T> Default for Weak<T> {
2065
2091
// clone these much in Rust thanks to ownership and move-semantics.
2066
2092
2067
2093
#[ doc( hidden) ]
2068
- trait RcBoxPtr < T : ?Sized > {
2069
- fn inner ( & self ) -> & RcBox < T > ;
2094
+ trait RcInnerPtr {
2095
+ fn weak_ref ( & self ) -> & Cell < usize > ;
2096
+ fn strong_ref ( & self ) -> & Cell < usize > ;
2070
2097
2071
2098
#[ inline]
2072
2099
fn strong ( & self ) -> usize {
2073
- self . inner ( ) . strong . get ( )
2100
+ self . strong_ref ( ) . get ( )
2074
2101
}
2075
2102
2076
2103
#[ inline]
@@ -2084,17 +2111,17 @@ trait RcBoxPtr<T: ?Sized> {
2084
2111
if strong == 0 || strong == usize:: MAX {
2085
2112
abort ( ) ;
2086
2113
}
2087
- self . inner ( ) . strong . set ( strong + 1 ) ;
2114
+ self . strong_ref ( ) . set ( strong + 1 ) ;
2088
2115
}
2089
2116
2090
2117
#[ inline]
2091
2118
fn dec_strong ( & self ) {
2092
- self . inner ( ) . strong . set ( self . strong ( ) - 1 ) ;
2119
+ self . strong_ref ( ) . set ( self . strong ( ) - 1 ) ;
2093
2120
}
2094
2121
2095
2122
#[ inline]
2096
2123
fn weak ( & self ) -> usize {
2097
- self . inner ( ) . weak . get ( )
2124
+ self . weak_ref ( ) . get ( )
2098
2125
}
2099
2126
2100
2127
#[ inline]
@@ -2108,26 +2135,36 @@ trait RcBoxPtr<T: ?Sized> {
2108
2135
if weak == 0 || weak == usize:: MAX {
2109
2136
abort ( ) ;
2110
2137
}
2111
- self . inner ( ) . weak . set ( weak + 1 ) ;
2138
+ self . weak_ref ( ) . set ( weak + 1 ) ;
2112
2139
}
2113
2140
2114
2141
#[ inline]
2115
2142
fn dec_weak ( & self ) {
2116
- self . inner ( ) . weak . set ( self . weak ( ) - 1 ) ;
2143
+ self . weak_ref ( ) . set ( self . weak ( ) - 1 ) ;
2117
2144
}
2118
2145
}
2119
2146
2120
- impl < T : ?Sized > RcBoxPtr < T > for Rc < T > {
2147
+ impl < T : ?Sized > RcInnerPtr for RcBox < T > {
2121
2148
#[ inline( always) ]
2122
- fn inner ( & self ) -> & RcBox < T > {
2123
- unsafe { self . ptr . as_ref ( ) }
2149
+ fn weak_ref ( & self ) -> & Cell < usize > {
2150
+ & self . weak
2151
+ }
2152
+
2153
+ #[ inline( always) ]
2154
+ fn strong_ref ( & self ) -> & Cell < usize > {
2155
+ & self . strong
2124
2156
}
2125
2157
}
2126
2158
2127
- impl < T : ? Sized > RcBoxPtr < T > for RcBox < T > {
2159
+ impl < ' a > RcInnerPtr for WeakInner < ' a > {
2128
2160
#[ inline( always) ]
2129
- fn inner ( & self ) -> & RcBox < T > {
2130
- self
2161
+ fn weak_ref ( & self ) -> & Cell < usize > {
2162
+ self . weak
2163
+ }
2164
+
2165
+ #[ inline( always) ]
2166
+ fn strong_ref ( & self ) -> & Cell < usize > {
2167
+ self . strong
2131
2168
}
2132
2169
}
2133
2170
0 commit comments