@@ -247,6 +247,7 @@ use crate::boxed::Box;
247247#[ cfg( test) ]
248248use std:: boxed:: Box ;
249249
250+ use core:: alloc:: helper:: PrefixAllocator ;
250251use core:: any:: Any ;
251252use core:: borrow;
252253use core:: cell:: Cell ;
@@ -257,7 +258,7 @@ use core::hash::{Hash, Hasher};
257258use core:: intrinsics:: abort;
258259use core:: iter;
259260use core:: marker:: { self , PhantomData , Unpin , Unsize } ;
260- use core:: mem:: { self , align_of_val_raw , forget, size_of_val} ;
261+ use core:: mem:: { self , forget, size_of_val, MaybeUninit } ;
261262use core:: ops:: { CoerceUnsized , Deref , DispatchFromDyn , Receiver } ;
262263use core:: pin:: Pin ;
263264use core:: ptr:: { self , NonNull } ;
@@ -273,13 +274,33 @@ use crate::vec::Vec;
273274#[ cfg( test) ]
274275mod tests;
275276
277+ struct RcBoxMetadata {
278+ strong : Cell < usize > ,
279+ weak : Cell < usize > ,
280+ }
281+
282+ impl RcBoxMetadata {
283+ // There is an implicit weak pointer owned by all the strong
284+ // pointers, which ensures that the weak destructor never frees
285+ // the allocation while the strong destructor is running, even
286+ // if the weak pointer is stored inside the strong one.
287+ #[ inline]
288+ fn new_strong ( ) -> Self {
289+ Self { strong : Cell :: new ( 1 ) , weak : Cell :: new ( 1 ) }
290+ }
291+
292+ #[ inline]
293+ fn new_weak ( ) -> Self {
294+ Self { strong : Cell :: new ( 0 ) , weak : Cell :: new ( 1 ) }
295+ }
296+ }
297+
276298// This is repr(C) to future-proof against possible field-reordering, which
277299// would interfere with otherwise safe [into|from]_raw() of transmutable
278300// inner types.
279301#[ repr( C ) ]
280302struct RcBox < T : ?Sized > {
281- strong : Cell < usize > ,
282- weak : Cell < usize > ,
303+ meta : RcBoxMetadata ,
283304 value : T ,
284305}
285306
@@ -319,10 +340,12 @@ impl<T: ?Sized> Rc<T> {
319340 unsafe { self . ptr . as_ref ( ) }
320341 }
321342
343+ #[ inline]
322344 fn from_inner ( ptr : NonNull < RcBox < T > > ) -> Self {
323345 Self { ptr, phantom : PhantomData }
324346 }
325347
348+ #[ inline]
326349 unsafe fn from_ptr ( ptr : * mut RcBox < T > ) -> Self {
327350 Self :: from_inner ( unsafe { NonNull :: new_unchecked ( ptr) } )
328351 }
@@ -340,13 +363,7 @@ impl<T> Rc<T> {
340363 /// ```
341364 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
342365 pub fn new ( value : T ) -> Rc < T > {
343- // There is an implicit weak pointer owned by all the strong
344- // pointers, which ensures that the weak destructor never frees
345- // the allocation while the strong destructor is running, even
346- // if the weak pointer is stored inside the strong one.
347- Self :: from_inner (
348- Box :: leak ( box RcBox { strong : Cell :: new ( 1 ) , weak : Cell :: new ( 1 ) , value } ) . into ( ) ,
349- )
366+ Self :: from_inner ( Box :: leak ( box RcBox { meta : RcBoxMetadata :: new_strong ( ) , value } ) . into ( ) )
350367 }
351368
352369 /// Constructs a new `Rc<T>` using a weak reference to itself. Attempting
@@ -378,8 +395,7 @@ impl<T> Rc<T> {
378395 // Construct the inner in the "uninitialized" state with a single
379396 // weak reference.
380397 let uninit_ptr: NonNull < _ > = Box :: leak ( box RcBox {
381- strong : Cell :: new ( 0 ) ,
382- weak : Cell :: new ( 1 ) ,
398+ meta : RcBoxMetadata :: new_weak ( ) ,
383399 value : mem:: MaybeUninit :: < T > :: uninit ( ) ,
384400 } )
385401 . into ( ) ;
@@ -400,9 +416,9 @@ impl<T> Rc<T> {
400416 let inner = init_ptr. as_ptr ( ) ;
401417 ptr:: write ( ptr:: addr_of_mut!( ( * inner) . value) , data) ;
402418
403- let prev_value = ( * inner) . strong . get ( ) ;
419+ let prev_value = ( * inner) . meta . strong . get ( ) ;
404420 debug_assert_eq ! ( prev_value, 0 , "No prior strong references should exist" ) ;
405- ( * inner) . strong . set ( 1 ) ;
421+ ( * inner) . meta . strong . set ( 1 ) ;
406422 }
407423
408424 let strong = Rc :: from_inner ( init_ptr) ;
@@ -494,8 +510,7 @@ impl<T> Rc<T> {
494510 // the allocation while the strong destructor is running, even
495511 // if the weak pointer is stored inside the strong one.
496512 Ok ( Self :: from_inner (
497- Box :: leak ( Box :: try_new ( RcBox { strong : Cell :: new ( 1 ) , weak : Cell :: new ( 1 ) , value } ) ?)
498- . into ( ) ,
513+ Box :: leak ( Box :: try_new ( RcBox { meta : RcBoxMetadata :: new_strong ( ) , value } ) ?) . into ( ) ,
499514 ) )
500515 }
501516
@@ -846,13 +861,7 @@ impl<T: ?Sized> Rc<T> {
846861 /// ```
847862 #[ stable( feature = "rc_raw" , since = "1.17.0" ) ]
848863 pub unsafe fn from_raw ( ptr : * const T ) -> Self {
849- let offset = unsafe { data_offset ( ptr) } ;
850-
851- // Reverse the offset to find the original RcBox.
852- let rc_ptr =
853- unsafe { ( ptr as * mut RcBox < T > ) . set_ptr_value ( ( ptr as * mut u8 ) . offset ( -offset) ) } ;
854-
855- unsafe { Self :: from_ptr ( rc_ptr) }
864+ unsafe { Self :: from_data_ptr ( ptr) . assume_init ( ) }
856865 }
857866
858867 /// Creates a new [`Weak`] pointer to this allocation.
@@ -1237,8 +1246,8 @@ impl<T: ?Sized> Rc<T> {
12371246 unsafe {
12381247 debug_assert_eq ! ( Layout :: for_value( & * inner) , layout) ;
12391248
1240- ptr:: write ( & mut ( * inner) . strong , Cell :: new ( 1 ) ) ;
1241- ptr:: write ( & mut ( * inner) . weak , Cell :: new ( 1 ) ) ;
1249+ ptr:: write ( & mut ( * inner) . meta . strong , Cell :: new ( 1 ) ) ;
1250+ ptr:: write ( & mut ( * inner) . meta . weak , Cell :: new ( 1 ) ) ;
12421251 }
12431252
12441253 Ok ( inner)
@@ -1277,6 +1286,23 @@ impl<T: ?Sized> Rc<T> {
12771286 Self :: from_ptr ( ptr)
12781287 }
12791288 }
1289+
1290+ /// # Safety
1291+ ///
1292+ /// The caller must ensure that the pointer points to the `value` field of a `Global`
1293+ /// allocation of type `RcBox<T>`. Depending on how the pointer was created, the
1294+ /// `meta` field might or might not be uninitialized. It's up to the caller to ensure
1295+ /// that this field is set to the correct value before the return value is unwrapped.
1296+ #[ inline]
1297+ unsafe fn from_data_ptr ( ptr : * const T ) -> MaybeUninit < Self > {
1298+ let offset = unsafe { data_offset ( ptr) } ;
1299+
1300+ // Reverse the offset to find the original RcBox.
1301+ let rc_ptr =
1302+ unsafe { ( ptr as * mut RcBox < T > ) . set_ptr_value ( ( ptr as * mut u8 ) . offset ( -offset) ) } ;
1303+
1304+ unsafe { MaybeUninit :: new ( Self :: from_ptr ( rc_ptr) ) }
1305+ }
12801306}
12811307
12821308impl < T > Rc < [ T ] > {
@@ -2206,7 +2232,7 @@ impl<T: ?Sized> Weak<T> {
22062232 // is dropped, the data field will be dropped in-place).
22072233 Some ( unsafe {
22082234 let ptr = self . ptr . as_ptr ( ) ;
2209- WeakInner { strong : & ( * ptr) . strong , weak : & ( * ptr) . weak }
2235+ WeakInner { strong : & ( * ptr) . meta . strong , weak : & ( * ptr) . meta . weak }
22102236 } )
22112237 }
22122238 }
@@ -2415,12 +2441,12 @@ trait RcInnerPtr {
24152441impl < T : ?Sized > RcInnerPtr for RcBox < T > {
24162442 #[ inline( always) ]
24172443 fn weak_ref ( & self ) -> & Cell < usize > {
2418- & self . weak
2444+ & self . meta . weak
24192445 }
24202446
24212447 #[ inline( always) ]
24222448 fn strong_ref ( & self ) -> & Cell < usize > {
2423- & self . strong
2449+ & self . meta . strong
24242450 }
24252451}
24262452
@@ -2453,24 +2479,21 @@ impl<T: ?Sized> AsRef<T> for Rc<T> {
24532479#[ stable( feature = "pin" , since = "1.33.0" ) ]
24542480impl < T : ?Sized > Unpin for Rc < T > { }
24552481
2482+ type RcAllocator = PrefixAllocator < RcBoxMetadata , Global > ;
2483+
24562484/// Get the offset within an `RcBox` for the payload behind a pointer.
24572485///
24582486/// # Safety
24592487///
24602488/// The pointer must point to (and have valid metadata for) a previously
24612489/// valid instance of T, but the T is allowed to be dropped.
24622490unsafe fn data_offset < T : ?Sized > ( ptr : * const T ) -> isize {
2463- // Align the unsized value to the end of the RcBox.
2464- // Because RcBox is repr(C), it will always be the last field in memory.
2465- // SAFETY: since the only unsized types possible are slices, trait objects,
2466- // and extern types, the input safety requirement is currently enough to
2467- // satisfy the requirements of align_of_val_raw; this is an implementation
2468- // detail of the language that may not be relied upon outside of std.
2469- unsafe { data_offset_align ( align_of_val_raw ( ptr) ) }
2470- }
2471-
2472- #[ inline]
2473- fn data_offset_align ( align : usize ) -> isize {
2474- let layout = Layout :: new :: < RcBox < ( ) > > ( ) ;
2475- ( layout. size ( ) + layout. padding_needed_for ( align) ) as isize
2491+ unsafe {
2492+ // SAFETY: since the only unsized types possible are slices, trait objects,
2493+ // and extern types, the input safety requirement is currently enough to
2494+ // satisfy the requirements of for_value_raw; this is an implementation
2495+ // detail of the language that may not be relied upon outside of std.
2496+ let layout = Layout :: for_value_raw ( ptr) ;
2497+ RcAllocator :: prefix_offset ( layout) as isize
2498+ }
24762499}
0 commit comments