@@ -532,6 +532,68 @@ impl<T, const N: usize> [T; N] {
532
532
}
533
533
}
534
534
535
+ struct Guard < T , const N : usize > {
536
+ ptr : * mut T ,
537
+ initialized : usize ,
538
+ }
539
+
540
+ impl < T , const N : usize > Drop for Guard < T , N > {
541
+ fn drop ( & mut self ) {
542
+ debug_assert ! ( self . initialized <= N ) ;
543
+
544
+ let initialized_part = crate :: ptr:: slice_from_raw_parts_mut ( self . ptr , self . initialized ) ;
545
+
546
+ // SAFETY: this raw slice will contain only initialized objects.
547
+ unsafe {
548
+ crate :: ptr:: drop_in_place ( initialized_part) ;
549
+ }
550
+ }
551
+ }
552
+
553
+ /// Creates a new array where each element is initialized by calling the
554
+ /// provided closure `F: FnMut(usize) -> T` with the index of each element.
555
+ ///
556
+ /// This allows initializing an array with elements that are not `Copy` or
557
+ /// `const` and where writing out the entire array literal as opposed to
558
+ /// `[expr; N]` is too verbose or not possible.
559
+ ///
560
+ /// # Example
561
+ ///
562
+ /// ```
563
+ /// #![feature(array_from_fn)]
564
+ ///
565
+ /// let array = std::array::from_fn(|index| 2 * index);
566
+ /// assert_eq!(array, [0, 2, 4, 6]);
567
+ /// ```
568
+ #[ unstable( feature = "array_from_fn" , issue = "none" ) ]
569
+ pub fn from_fn < T , F , const N : usize > ( mut f : F ) -> [ T ; N ]
570
+ where
571
+ F : FnMut ( usize ) -> T ,
572
+ {
573
+ let mut array = MaybeUninit :: uninit_array :: < N > ( ) ;
574
+ let mut guard: Guard < _ , N > =
575
+ Guard { ptr : MaybeUninit :: slice_as_mut_ptr ( & mut array) , initialized : 0 } ;
576
+
577
+ while guard. initialized < N {
578
+ let item = f ( guard. initialized ) ;
579
+
580
+ // SAFETY: `guard.initialized` starts at 0, is increased by one in the
581
+ // loop and the loop is aborted once it reaches N (which is
582
+ // `array.len()`).
583
+ unsafe {
584
+ array. get_unchecked_mut ( guard. initialized ) . write ( item) ;
585
+ }
586
+
587
+ guard. initialized += 1 ;
588
+ }
589
+
590
+ mem:: forget ( guard) ;
591
+
592
+ // SAFETY: the condition above asserts that all elements are
593
+ // initialized.
594
+ unsafe { MaybeUninit :: array_assume_init ( array) }
595
+ }
596
+
535
597
/// Pulls `N` items from `iter` and returns them as an array. If the iterator
536
598
/// yields fewer than `N` items, this function exhibits undefined behavior.
537
599
///
@@ -568,7 +630,7 @@ where
568
630
/// `next` at most `N` times, the iterator can still be used afterwards to
569
631
/// retrieve the remaining items.
570
632
///
571
- /// If `iter.next()` panicks , all items already yielded by the iterator are
633
+ /// If `iter.next()` panics , all items already yielded by the iterator are
572
634
/// dropped.
573
635
fn collect_into_array < I , const N : usize > ( iter : & mut I ) -> Option < [ I :: Item ; N ] >
574
636
where
@@ -579,24 +641,6 @@ where
579
641
return unsafe { Some ( mem:: zeroed ( ) ) } ;
580
642
}
581
643
582
- struct Guard < T , const N : usize > {
583
- ptr : * mut T ,
584
- initialized : usize ,
585
- }
586
-
587
- impl < T , const N : usize > Drop for Guard < T , N > {
588
- fn drop ( & mut self ) {
589
- debug_assert ! ( self . initialized <= N ) ;
590
-
591
- let initialized_part = crate :: ptr:: slice_from_raw_parts_mut ( self . ptr , self . initialized ) ;
592
-
593
- // SAFETY: this raw slice will contain only initialized objects.
594
- unsafe {
595
- crate :: ptr:: drop_in_place ( initialized_part) ;
596
- }
597
- }
598
- }
599
-
600
644
let mut array = MaybeUninit :: uninit_array :: < N > ( ) ;
601
645
let mut guard: Guard < _ , N > =
602
646
Guard { ptr : MaybeUninit :: slice_as_mut_ptr ( & mut array) , initialized : 0 } ;
0 commit comments