@@ -385,6 +385,55 @@ where
385
385
Ord :: cmp ( & & self [ ..] , & & other[ ..] )
386
386
}
387
387
}
388
+ #[ stable( since = "1.4.0" , feature = "array_default" ) ]
389
+ impl < T : Default , const N : usize > Default for [ T ; N ]
390
+ where
391
+ [ T ; N ] : LengthAtMost32 ,
392
+ {
393
+ #[ inline]
394
+ fn default ( ) -> [ T ; N ] {
395
+ use crate :: mem:: MaybeUninit ;
396
+ // invariant: first `init` items are initialized
397
+ struct Wrapper < T , const N : usize > {
398
+ data : MaybeUninit < [ T ; N ] > ,
399
+ init : usize ,
400
+ }
401
+
402
+ impl < T , const N : usize > Drop for Wrapper < T , N > {
403
+ fn drop ( & mut self ) {
404
+ debug_assert ! ( self . init <= N ) ;
405
+ let ptr = self . data . as_mut_ptr ( ) as * mut T ;
406
+ for i in 0 ..self . init {
407
+ // SAFETY: we iterate over only initialized values.
408
+ // Each value is dropped once.
409
+ unsafe {
410
+ crate :: ptr:: drop_in_place ( ptr. add ( i) ) ;
411
+ }
412
+ }
413
+ }
414
+ }
415
+
416
+ let mut w = Wrapper :: < T , N > { data : MaybeUninit :: uninit ( ) , init : 0 } ;
417
+ let array_pointer = w. data . as_mut_ptr ( ) as * mut T ;
418
+ for i in 0 ..N {
419
+ // FIXME: this does not work for big N.
420
+ // Currently it is acceptable, because N <= 32.
421
+ assert ! ( N <= isize :: MAX as usize ) ;
422
+ // SAFETY: i < N <= isize::MAX, so add() is correct
423
+ unsafe {
424
+ let elem_ptr = array_pointer. add ( i) ;
425
+ elem_ptr. write ( T :: default ( ) ) ;
426
+ }
427
+ w. init += 1 ;
428
+ }
429
+
430
+ // Prevent double-read in callee and Wrepper::drop
431
+ w. init = 0 ;
432
+
433
+ // SAFETY: all arraty is initialized now.
434
+ unsafe { w. data . as_ptr ( ) . read ( ) }
435
+ }
436
+ }
388
437
389
438
/// Implemented for lengths where trait impls are allowed on arrays in core/std
390
439
#[ rustc_on_unimplemented( message = "arrays only have std trait implementations for lengths 0..=32" ) ]
@@ -410,26 +459,3 @@ array_impls! {
410
459
20 21 22 23 24 25 26 27 28 29
411
460
30 31 32
412
461
}
413
-
414
- // The Default impls cannot be generated using the array_impls! macro because
415
- // they require array literals.
416
-
417
- macro_rules! array_impl_default {
418
- { $n: expr, $t: ident $( $ts: ident) * } => {
419
- #[ stable( since = "1.4.0" , feature = "array_default" ) ]
420
- impl <T > Default for [ T ; $n] where T : Default {
421
- fn default ( ) -> [ T ; $n] {
422
- [ $t:: default ( ) , $( $ts:: default ( ) ) ,* ]
423
- }
424
- }
425
- array_impl_default!{ ( $n - 1 ) , $( $ts) * }
426
- } ;
427
- { $n: expr, } => {
428
- #[ stable( since = "1.4.0" , feature = "array_default" ) ]
429
- impl <T > Default for [ T ; $n] {
430
- fn default ( ) -> [ T ; $n] { [ ] }
431
- }
432
- } ;
433
- }
434
-
435
- 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