@@ -2496,6 +2496,14 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Arc<T, A> {
2496
2496
// [2]: (https://github.com/rust-lang/rust/pull/41714)
2497
2497
acquire ! ( self . inner( ) . strong) ;
2498
2498
2499
+ // Make sure we aren't trying to "drop" the shared static for empty slices
2500
+ // used by Default::default.
2501
+ debug_assert ! (
2502
+ !ptr:: addr_eq( self . ptr. as_ptr( ) , & STATIC_INNER_SLICE . inner) ,
2503
+ "Arcs backed by a static should never reach a strong count of 0. \
2504
+ Likely decrement_strong_count or from_raw were called too many times.",
2505
+ ) ;
2506
+
2499
2507
unsafe {
2500
2508
self . drop_slow ( ) ;
2501
2509
}
@@ -3126,6 +3134,15 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Weak<T, A> {
3126
3134
3127
3135
if inner. weak . fetch_sub ( 1 , Release ) == 1 {
3128
3136
acquire ! ( inner. weak) ;
3137
+
3138
+ // Make sure we aren't trying to "deallocate" the shared static for empty slices
3139
+ // used by Default::default.
3140
+ debug_assert ! (
3141
+ !ptr:: addr_eq( self . ptr. as_ptr( ) , & STATIC_INNER_SLICE . inner) ,
3142
+ "Arc/Weaks backed by a static should never be deallocated. \
3143
+ Likely decrement_strong_count or from_raw were called too many times.",
3144
+ ) ;
3145
+
3129
3146
unsafe {
3130
3147
self . alloc . deallocate ( self . ptr . cast ( ) , Layout :: for_value_raw ( self . ptr . as_ptr ( ) ) )
3131
3148
}
@@ -3367,6 +3384,28 @@ impl<T: Default> Default for Arc<T> {
3367
3384
}
3368
3385
}
3369
3386
3387
+ /// Struct to hold the static `ArcInner` used for empty `Arc<str/CStr/[T]>` as
3388
+ /// returned by `Default::default`.
3389
+ ///
3390
+ /// Layout notes:
3391
+ /// * `repr(align(16))` so we can use it for `[T]` with `align_of::<T>() <= 16`.
3392
+ /// * `repr(C)` so `inner` is at offset 0 (and thus guaranteed to actually be aligned to 16).
3393
+ /// * `[u8; 1]` (to be initialized with 0) so it can be used for `Arc<CStr>`.
3394
+ #[ repr( C , align( 16 ) ) ]
3395
+ struct SliceArcInnerForStatic {
3396
+ inner : ArcInner < [ u8 ; 1 ] > ,
3397
+ }
3398
+ #[ cfg( not( no_global_oom_handling) ) ]
3399
+ const MAX_STATIC_INNER_SLICE_ALIGNMENT : usize = 16 ;
3400
+
3401
+ static STATIC_INNER_SLICE : SliceArcInnerForStatic = SliceArcInnerForStatic {
3402
+ inner : ArcInner {
3403
+ strong : atomic:: AtomicUsize :: new ( 1 ) ,
3404
+ weak : atomic:: AtomicUsize :: new ( 1 ) ,
3405
+ data : [ 0 ] ,
3406
+ } ,
3407
+ } ;
3408
+
3370
3409
#[ cfg( not( no_global_oom_handling) ) ]
3371
3410
#[ stable( feature = "more_rc_default_impls" , since = "CURRENT_RUSTC_VERSION" ) ]
3372
3411
impl Default for Arc < str > {
@@ -3391,15 +3430,12 @@ impl Default for Arc<core::ffi::CStr> {
3391
3430
#[ inline]
3392
3431
fn default ( ) -> Self {
3393
3432
use core:: ffi:: CStr ;
3394
- static STATIC_INNER_CSTR : ArcInner < [ u8 ; 1 ] > = ArcInner {
3395
- strong : atomic:: AtomicUsize :: new ( 1 ) ,
3396
- weak : atomic:: AtomicUsize :: new ( 1 ) ,
3397
- data : [ 0 ] ,
3398
- } ;
3399
- let inner: NonNull < ArcInner < [ u8 ] > > = NonNull :: from ( & STATIC_INNER_CSTR ) ;
3400
- let inner: NonNull < ArcInner < CStr > > = NonNull :: new ( inner. as_ptr ( ) as * mut ArcInner < CStr > ) . unwrap ( ) ;
3433
+ let inner: NonNull < ArcInner < [ u8 ] > > = NonNull :: from ( & STATIC_INNER_SLICE . inner ) ;
3434
+ let inner: NonNull < ArcInner < CStr > > =
3435
+ NonNull :: new ( inner. as_ptr ( ) as * mut ArcInner < CStr > ) . unwrap ( ) ;
3401
3436
// `this` semantically is the Arc "owned" by the static, so make sure not to drop it.
3402
- let this: mem:: ManuallyDrop < Arc < CStr > > = unsafe { mem:: ManuallyDrop :: new ( Arc :: from_inner ( inner) ) } ;
3437
+ let this: mem:: ManuallyDrop < Arc < CStr > > =
3438
+ unsafe { mem:: ManuallyDrop :: new ( Arc :: from_inner ( inner) ) } ;
3403
3439
( * this) . clone ( )
3404
3440
}
3405
3441
}
@@ -3412,31 +3448,20 @@ impl<T> Default for Arc<[T]> {
3412
3448
/// This may or may not share an allocation with other Arcs.
3413
3449
#[ inline]
3414
3450
fn default ( ) -> Self {
3415
- let alignment_of_t: usize = mem:: align_of :: < T > ( ) ;
3416
- // We only make statics for the lowest five alignments.
3417
- // Alignments greater than that will use dynamic allocation.
3418
- macro_rules! use_static_inner_for_alignments {
3419
- ( $( $alignment: literal) ,* ) => {
3420
- $( if alignment_of_t == $alignment {
3421
- // Note: this must be in a new scope because static and type names are unhygenic.
3422
- #[ repr( align( $alignment) ) ]
3423
- struct Aligned ;
3424
- static ALIGNED_STATIC_INNER : ArcInner <Aligned > = ArcInner {
3425
- strong: atomic:: AtomicUsize :: new( 1 ) ,
3426
- weak: atomic:: AtomicUsize :: new( 1 ) ,
3427
- data: Aligned ,
3428
- } ;
3429
- let inner: NonNull <ArcInner <Aligned >> = NonNull :: from( & ALIGNED_STATIC_INNER ) ;
3430
- let inner: NonNull <ArcInner <[ T ; 0 ] >> = inner. cast( ) ;
3431
- // `this` semantically is the Arc "owned" by the static, so make sure not to drop it.
3432
- let this: mem:: ManuallyDrop <Arc <[ T ; 0 ] >> = unsafe { mem:: ManuallyDrop :: new( Arc :: from_inner( inner) ) } ;
3433
- return ( * this) . clone( ) ;
3434
- } ) *
3435
- } ;
3451
+ if mem:: align_of :: < T > ( ) <= MAX_STATIC_INNER_SLICE_ALIGNMENT {
3452
+ // We take a reference to the whole struct instead of the ArcInner<[u8; 1]> inside it so
3453
+ // we don't shrink the range of bytes the ptr is allowed to access under Stacked Borrows.
3454
+ // (Miri complains on 32-bit targets with Arc<[Align16]> otherwise.)
3455
+ // (Note that NonNull::from(&STATIC_INNER_SLICE.inner) is fine under Tree Borrows.)
3456
+ let inner: NonNull < SliceArcInnerForStatic > = NonNull :: from ( & STATIC_INNER_SLICE ) ;
3457
+ let inner: NonNull < ArcInner < [ T ; 0 ] > > = inner. cast ( ) ;
3458
+ // `this` semantically is the Arc "owned" by the static, so make sure not to drop it.
3459
+ let this: mem:: ManuallyDrop < Arc < [ T ; 0 ] > > =
3460
+ unsafe { mem:: ManuallyDrop :: new ( Arc :: from_inner ( inner) ) } ;
3461
+ return ( * this) . clone ( ) ;
3436
3462
}
3437
- use_static_inner_for_alignments ! ( 1 , 2 , 4 , 8 , 16 ) ;
3438
3463
3439
- // If T's alignment is not one of the ones we have a static for , make a new unique allocation.
3464
+ // If T's alignment is too large for the static, make a new unique allocation.
3440
3465
let arr: [ T ; 0 ] = [ ] ;
3441
3466
Arc :: from ( arr)
3442
3467
}
0 commit comments