@@ -385,6 +385,55 @@ where
385385 Ord :: cmp ( & & self [ ..] , & & other[ ..] )
386386 }
387387}
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+ }
388437
389438/// Implemented for lengths where trait impls are allowed on arrays in core/std
390439#[ rustc_on_unimplemented( message = "arrays only have std trait implementations for lengths 0..=32" ) ]
@@ -410,26 +459,3 @@ array_impls! {
410459 20 21 22 23 24 25 26 27 28 29
411460 30 31 32
412461}
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