@@ -387,6 +387,81 @@ where
387
387
}
388
388
}
389
389
390
+ /// A trait implemented by all arrays which are either empty or contain a type implementing `Default`.
391
+ #[ unstable( feature = "array_default_internals" , reason = "implementation detail" , issue = "none" ) ]
392
+ #[ marker]
393
+ pub trait ArrayDefault { }
394
+
395
+ #[ unstable( feature = "array_default_internals" , reason = "implementation detail" , issue = "none" ) ]
396
+ impl < T > ArrayDefault for [ T ; 0 ] { }
397
+
398
+ #[ unstable( feature = "array_default_internals" , reason = "implementation detail" , issue = "none" ) ]
399
+ impl < T : Default , const N : usize > ArrayDefault for [ T ; N ] { }
400
+
401
+ trait DefaultHack {
402
+ fn default_hack ( ) -> Self ;
403
+ }
404
+
405
+ impl < T > DefaultHack for T {
406
+ default fn default_hack ( ) -> Self {
407
+ unreachable ! ( ) ;
408
+ }
409
+ }
410
+
411
+ impl < T : Default > DefaultHack for T {
412
+ #[ inline( always) ]
413
+ fn default_hack ( ) -> Self {
414
+ Default :: default ( )
415
+ }
416
+ }
417
+
418
+ #[ stable( since = "1.4.0" , feature = "array_default" ) ]
419
+ impl < T , const N : usize > Default for [ T ; N ]
420
+ where
421
+ [ T ; N ] : ArrayDefault + LengthAtMost32 ,
422
+ {
423
+ #[ inline]
424
+ fn default ( ) -> [ T ; N ] {
425
+ use crate :: mem:: MaybeUninit ;
426
+ let mut data: MaybeUninit < [ T ; N ] > = MaybeUninit :: uninit ( ) ;
427
+ // Invariant: first `init` items are initialized
428
+ struct Guard < T , const N : usize > {
429
+ data : * mut T ,
430
+ init : usize ,
431
+ }
432
+
433
+ impl < T , const N : usize > Drop for Guard < T , N > {
434
+ #[ inline]
435
+ fn drop ( & mut self ) {
436
+ debug_assert ! ( self . init <= N ) ;
437
+
438
+ let initialized_part = crate :: ptr:: slice_from_raw_parts_mut ( self . data , self . init ) ;
439
+ // SAFETY: this raw slice will contain only initialized objects
440
+ // that's why, it is allowed to drop it.
441
+ unsafe {
442
+ crate :: ptr:: drop_in_place ( initialized_part) ;
443
+ }
444
+ }
445
+ }
446
+
447
+ let mut w = Guard :: < T , N > { data : data. as_mut_ptr ( ) as * mut T , init : 0 } ;
448
+ // SAFETY: in fact we go from &mut MaybeUninit<[T; N]> to &mut [MaybeUninit<T>; N].
449
+ // it is always correct.
450
+ let slots = unsafe { & mut * ( data. as_mut_ptr ( ) as * mut [ MaybeUninit < T > ; N ] ) } ;
451
+ for slot in slots. iter_mut ( ) {
452
+ slot. write ( T :: default_hack ( ) ) ;
453
+ // now, when slot is filled with value, we can increment
454
+ // `init`.
455
+ w. init += 1 ;
456
+ }
457
+
458
+ // Prevent double-read in callee and Wrapper::drop
459
+ crate :: mem:: forget ( w) ;
460
+ // SAFETY: at this point whole array is initialized.
461
+ unsafe { data. assume_init ( ) }
462
+ }
463
+ }
464
+
390
465
/// Implemented for lengths where trait impls are allowed on arrays in core/std
391
466
#[ rustc_on_unimplemented( message = "arrays only have std trait implementations for lengths 0..=32" ) ]
392
467
#[ unstable(
@@ -411,26 +486,3 @@ array_impls! {
411
486
20 21 22 23 24 25 26 27 28 29
412
487
30 31 32
413
488
}
414
-
415
- // The Default impls cannot be generated using the array_impls! macro because
416
- // they require array literals.
417
-
418
- macro_rules! array_impl_default {
419
- { $n: expr, $t: ident $( $ts: ident) * } => {
420
- #[ stable( since = "1.4.0" , feature = "array_default" ) ]
421
- impl <T > Default for [ T ; $n] where T : Default {
422
- fn default ( ) -> [ T ; $n] {
423
- [ $t:: default ( ) , $( $ts:: default ( ) ) ,* ]
424
- }
425
- }
426
- array_impl_default!{ ( $n - 1 ) , $( $ts) * }
427
- } ;
428
- { $n: expr, } => {
429
- #[ stable( since = "1.4.0" , feature = "array_default" ) ]
430
- impl <T > Default for [ T ; $n] {
431
- fn default ( ) -> [ T ; $n] { [ ] }
432
- }
433
- } ;
434
- }
435
-
436
- array_impl_default ! { 32 , T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T }
0 commit comments