@@ -257,12 +257,13 @@ use core::hash::{Hash, Hasher};
257
257
use core:: intrinsics:: abort;
258
258
use core:: iter;
259
259
use core:: marker:: { self , PhantomData , Unpin , Unsize } ;
260
- use core:: mem:: { self , align_of_val_raw , forget, size_of_val} ;
260
+ use core:: mem:: { self , forget, size_of_val} ;
261
261
use core:: ops:: { CoerceUnsized , Deref , DispatchFromDyn , Receiver } ;
262
262
use core:: pin:: Pin ;
263
263
use core:: ptr:: { self , NonNull } ;
264
264
use core:: slice:: from_raw_parts_mut;
265
265
266
+ use crate :: alloc:: struct_alloc:: StructAlloc ;
266
267
use crate :: alloc:: {
267
268
box_free, handle_alloc_error, AllocError , Allocator , Global , Layout , WriteCloneIntoRaw ,
268
269
} ;
@@ -273,13 +274,31 @@ use crate::vec::Vec;
273
274
#[ cfg( test) ]
274
275
mod tests;
275
276
276
- // This is repr(C) to future-proof against possible field-reordering, which
277
- // would interfere with otherwise safe [into|from]_raw() of transmutable
278
- // inner types.
279
- #[ repr( C ) ]
280
- struct RcBox < T : ?Sized > {
277
+ struct RcBoxMetadata {
281
278
strong : Cell < usize > ,
282
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
+
298
+ // This is repr(C) to support StructAlloc
299
+ #[ repr( C ) ]
300
+ struct RcBox < T : ?Sized > {
301
+ meta : RcBoxMetadata ,
283
302
value : T ,
284
303
}
285
304
@@ -340,13 +359,7 @@ impl<T> Rc<T> {
340
359
/// ```
341
360
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
342
361
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
- )
362
+ Self :: from_inner ( Box :: leak ( box RcBox { meta : RcBoxMetadata :: new_strong ( ) , value } ) . into ( ) )
350
363
}
351
364
352
365
/// Constructs a new `Rc<T>` using a weak reference to itself. Attempting
@@ -378,8 +391,7 @@ impl<T> Rc<T> {
378
391
// Construct the inner in the "uninitialized" state with a single
379
392
// weak reference.
380
393
let uninit_ptr: NonNull < _ > = Box :: leak ( box RcBox {
381
- strong : Cell :: new ( 0 ) ,
382
- weak : Cell :: new ( 1 ) ,
394
+ meta : RcBoxMetadata :: new_weak ( ) ,
383
395
value : mem:: MaybeUninit :: < T > :: uninit ( ) ,
384
396
} )
385
397
. into ( ) ;
@@ -400,9 +412,9 @@ impl<T> Rc<T> {
400
412
let inner = init_ptr. as_ptr ( ) ;
401
413
ptr:: write ( ptr:: addr_of_mut!( ( * inner) . value) , data) ;
402
414
403
- let prev_value = ( * inner) . strong . get ( ) ;
415
+ let prev_value = ( * inner) . meta . strong . get ( ) ;
404
416
debug_assert_eq ! ( prev_value, 0 , "No prior strong references should exist" ) ;
405
- ( * inner) . strong . set ( 1 ) ;
417
+ ( * inner) . meta . strong . set ( 1 ) ;
406
418
}
407
419
408
420
let strong = Rc :: from_inner ( init_ptr) ;
@@ -489,13 +501,8 @@ impl<T> Rc<T> {
489
501
/// ```
490
502
#[ unstable( feature = "allocator_api" , issue = "32838" ) ]
491
503
pub fn try_new ( value : T ) -> Result < Rc < T > , AllocError > {
492
- // There is an implicit weak pointer owned by all the strong
493
- // pointers, which ensures that the weak destructor never frees
494
- // the allocation while the strong destructor is running, even
495
- // if the weak pointer is stored inside the strong one.
496
504
Ok ( Self :: from_inner (
497
- Box :: leak ( Box :: try_new ( RcBox { strong : Cell :: new ( 1 ) , weak : Cell :: new ( 1 ) , value } ) ?)
498
- . into ( ) ,
505
+ Box :: leak ( Box :: try_new ( RcBox { meta : RcBoxMetadata :: new_strong ( ) , value } ) ?) . into ( ) ,
499
506
) )
500
507
}
501
508
@@ -1170,8 +1177,8 @@ impl<T: ?Sized> Rc<T> {
1170
1177
unsafe {
1171
1178
debug_assert_eq ! ( Layout :: for_value( & * inner) , layout) ;
1172
1179
1173
- ptr:: write ( & mut ( * inner) . strong , Cell :: new ( 1 ) ) ;
1174
- ptr:: write ( & mut ( * inner) . weak , Cell :: new ( 1 ) ) ;
1180
+ ptr:: write ( & mut ( * inner) . meta . strong , Cell :: new ( 1 ) ) ;
1181
+ ptr:: write ( & mut ( * inner) . meta . weak , Cell :: new ( 1 ) ) ;
1175
1182
}
1176
1183
1177
1184
Ok ( inner)
@@ -2087,7 +2094,7 @@ impl<T: ?Sized> Weak<T> {
2087
2094
// is dropped, the data field will be dropped in-place).
2088
2095
Some ( unsafe {
2089
2096
let ptr = self . ptr . as_ptr ( ) ;
2090
- WeakInner { strong : & ( * ptr) . strong , weak : & ( * ptr) . weak }
2097
+ WeakInner { strong : & ( * ptr) . meta . strong , weak : & ( * ptr) . meta . weak }
2091
2098
} )
2092
2099
}
2093
2100
}
@@ -2296,12 +2303,12 @@ trait RcInnerPtr {
2296
2303
impl < T : ?Sized > RcInnerPtr for RcBox < T > {
2297
2304
#[ inline( always) ]
2298
2305
fn weak_ref ( & self ) -> & Cell < usize > {
2299
- & self . weak
2306
+ & self . meta . weak
2300
2307
}
2301
2308
2302
2309
#[ inline( always) ]
2303
2310
fn strong_ref ( & self ) -> & Cell < usize > {
2304
- & self . strong
2311
+ & self . meta . strong
2305
2312
}
2306
2313
}
2307
2314
@@ -2334,24 +2341,21 @@ impl<T: ?Sized> AsRef<T> for Rc<T> {
2334
2341
#[ stable( feature = "pin" , since = "1.33.0" ) ]
2335
2342
impl < T : ?Sized > Unpin for Rc < T > { }
2336
2343
2344
+ type RcStructAlloc = StructAlloc < RcBoxMetadata > ;
2345
+
2337
2346
/// Get the offset within an `RcBox` for the payload behind a pointer.
2338
2347
///
2339
2348
/// # Safety
2340
2349
///
2341
2350
/// The pointer must point to (and have valid metadata for) a previously
2342
2351
/// valid instance of T, but the T is allowed to be dropped.
2343
- unsafe fn data_offset < T : ?Sized > ( ptr : * const T ) -> isize {
2344
- // Align the unsized value to the end of the RcBox.
2345
- // Because RcBox is repr(C), it will always be the last field in memory.
2346
- // SAFETY: since the only unsized types possible are slices, trait objects,
2347
- // and extern types, the input safety requirement is currently enough to
2348
- // satisfy the requirements of align_of_val_raw; this is an implementation
2349
- // detail of the language that may not be relied upon outside of std.
2350
- unsafe { data_offset_align ( align_of_val_raw ( ptr) ) }
2351
- }
2352
-
2353
- #[ inline]
2354
- fn data_offset_align ( align : usize ) -> isize {
2355
- let layout = Layout :: new :: < RcBox < ( ) > > ( ) ;
2356
- ( layout. size ( ) + layout. padding_needed_for ( align) ) as isize
2352
+ unsafe fn data_offset < T : ?Sized > ( data_ptr : * const T ) -> isize {
2353
+ unsafe {
2354
+ // SAFETY: since the only unsized types possible are slices, trait objects,
2355
+ // and extern types, the input safety requirement is currently enough to
2356
+ // satisfy the requirements of for_value_raw; this is an implementation
2357
+ // detail of the language that may not be relied upon outside of std.
2358
+ let data_layout = Layout :: for_value_raw ( data_ptr) ;
2359
+ RcStructAlloc :: offset_of_data ( data_layout) as isize
2360
+ }
2357
2361
}
0 commit comments