@@ -2468,6 +2468,15 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Arc<T, A> {
2468
2468
// [2]: (https://github.com/rust-lang/rust/pull/41714)
2469
2469
acquire ! ( self . inner( ) . strong) ;
2470
2470
2471
+ // Make sure we aren't trying to "drop" the shared static for empty slices
2472
+ // used by Default::default.
2473
+ debug_assert ! (
2474
+ !ptr:: addr_eq( self . ptr. as_ptr( ) , & STATIC_INNER_SLICE . inner) ,
2475
+ "Arcs backed by a static should never be reach a strong count of 0. \
2476
+ Likely decrement_strong_count or from_raw were called too many times.",
2477
+ ) ;
2478
+
2479
+
2471
2480
unsafe {
2472
2481
self . drop_slow ( ) ;
2473
2482
}
@@ -3059,6 +3068,15 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Weak<T, A> {
3059
3068
3060
3069
if inner. weak . fetch_sub ( 1 , Release ) == 1 {
3061
3070
acquire ! ( inner. weak) ;
3071
+
3072
+ // Make sure we aren't trying to "deallocate" the shared static for empty slices
3073
+ // used by Default::default.
3074
+ debug_assert ! (
3075
+ !ptr:: addr_eq( self . ptr. as_ptr( ) , & STATIC_INNER_SLICE . inner) ,
3076
+ "Arc/Weaks backed by a static should never be deallocated. \
3077
+ Likely decrement_strong_count or from_raw were called too many times.",
3078
+ ) ;
3079
+
3062
3080
unsafe {
3063
3081
self . alloc . deallocate ( self . ptr . cast ( ) , Layout :: for_value_raw ( self . ptr . as_ptr ( ) ) )
3064
3082
}
@@ -3300,6 +3318,28 @@ impl<T: Default> Default for Arc<T> {
3300
3318
}
3301
3319
}
3302
3320
3321
+ /// Struct to hold the static `ArcInner` used for empty `Arc<str/CStr/[T]>` as
3322
+ /// returned by `Default::default`.
3323
+ ///
3324
+ /// Layout notes:
3325
+ /// * `repr(align(16))` so we can use it for `[T]` with `align_of::<T>() <= 16`.
3326
+ /// * `repr(C)` so `inner` is at offset 0 (and thus guaranteed to actually be aligned to 16).
3327
+ /// * `[u8; 1]` (to be initialized with 0) so it can be used for `Arc<CStr>`.
3328
+ #[ repr( C , align( 16 ) ) ]
3329
+ struct SliceArcInnerForStatic {
3330
+ inner : ArcInner < [ u8 ; 1 ] > ,
3331
+ }
3332
+ const MAX_STATIC_INNER_SLICE_ALIGNMENT : usize = 16 ;
3333
+
3334
+ static STATIC_INNER_SLICE : SliceArcInnerForStatic = SliceArcInnerForStatic {
3335
+ inner : ArcInner {
3336
+ strong : atomic:: AtomicUsize :: new ( 1 ) ,
3337
+ weak : atomic:: AtomicUsize :: new ( 1 ) ,
3338
+ data : [ 0 ] ,
3339
+ } ,
3340
+ } ;
3341
+
3342
+
3303
3343
#[ cfg( not( no_global_oom_handling) ) ]
3304
3344
#[ stable( feature = "more_rc_default_impls" , since = "CURRENT_RUSTC_VERSION" ) ]
3305
3345
impl Default for Arc < str > {
@@ -3324,12 +3364,7 @@ impl Default for Arc<core::ffi::CStr> {
3324
3364
#[ inline]
3325
3365
fn default ( ) -> Self {
3326
3366
use core:: ffi:: CStr ;
3327
- static STATIC_INNER_CSTR : ArcInner < [ u8 ; 1 ] > = ArcInner {
3328
- strong : atomic:: AtomicUsize :: new ( 1 ) ,
3329
- weak : atomic:: AtomicUsize :: new ( 1 ) ,
3330
- data : [ 0 ] ,
3331
- } ;
3332
- let inner: NonNull < ArcInner < [ u8 ] > > = NonNull :: from ( & STATIC_INNER_CSTR ) ;
3367
+ let inner: NonNull < ArcInner < [ u8 ] > > = NonNull :: from ( & STATIC_INNER_SLICE . inner ) ;
3333
3368
let inner: NonNull < ArcInner < CStr > > = NonNull :: new ( inner. as_ptr ( ) as * mut ArcInner < CStr > ) . unwrap ( ) ;
3334
3369
// `this` semantically is the Arc "owned" by the static, so make sure not to drop it.
3335
3370
let this: mem:: ManuallyDrop < Arc < CStr > > = unsafe { mem:: ManuallyDrop :: new ( Arc :: from_inner ( inner) ) } ;
@@ -3345,31 +3380,15 @@ impl<T> Default for Arc<[T]> {
3345
3380
/// This may or may not share an allocation with other Arcs.
3346
3381
#[ inline]
3347
3382
fn default ( ) -> Self {
3348
- let alignment_of_t: usize = mem:: align_of :: < T > ( ) ;
3349
- // We only make statics for the lowest five alignments.
3350
- // Alignments greater than that will use dynamic allocation.
3351
- macro_rules! use_static_inner_for_alignments {
3352
- ( $( $alignment: literal) ,* ) => {
3353
- $( if alignment_of_t == $alignment {
3354
- // Note: this must be in a new scope because static and type names are unhygenic.
3355
- #[ repr( align( $alignment) ) ]
3356
- struct Aligned ;
3357
- static ALIGNED_STATIC_INNER : ArcInner <Aligned > = ArcInner {
3358
- strong: atomic:: AtomicUsize :: new( 1 ) ,
3359
- weak: atomic:: AtomicUsize :: new( 1 ) ,
3360
- data: Aligned ,
3361
- } ;
3362
- let inner: NonNull <ArcInner <Aligned >> = NonNull :: from( & ALIGNED_STATIC_INNER ) ;
3363
- let inner: NonNull <ArcInner <[ T ; 0 ] >> = inner. cast( ) ;
3364
- // `this` semantically is the Arc "owned" by the static, so make sure not to drop it.
3365
- let this: mem:: ManuallyDrop <Arc <[ T ; 0 ] >> = unsafe { mem:: ManuallyDrop :: new( Arc :: from_inner( inner) ) } ;
3366
- return ( * this) . clone( ) ;
3367
- } ) *
3368
- } ;
3383
+ if mem:: align_of :: < T > ( ) <= MAX_STATIC_INNER_SLICE_ALIGNMENT {
3384
+ let inner: NonNull < ArcInner < [ u8 ; 1 ] > > = NonNull :: from ( & STATIC_INNER_SLICE . inner ) ;
3385
+ let inner: NonNull < ArcInner < [ T ; 0 ] > > = inner. cast ( ) ;
3386
+ // `this` semantically is the Arc "owned" by the static, so make sure not to drop it.
3387
+ let this: mem:: ManuallyDrop < Arc < [ T ; 0 ] > > = unsafe { mem:: ManuallyDrop :: new ( Arc :: from_inner ( inner) ) } ;
3388
+ return ( * this) . clone ( ) ;
3369
3389
}
3370
- use_static_inner_for_alignments ! ( 1 , 2 , 4 , 8 , 16 ) ;
3371
3390
3372
- // If T's alignment is not one of the ones we have a static for , make a new unique allocation.
3391
+ // If T's alignment is too large for the static, make a new unique allocation.
3373
3392
let arr: [ T ; 0 ] = [ ] ;
3374
3393
Arc :: from ( arr)
3375
3394
}
0 commit comments