@@ -878,13 +878,11 @@ where
878
878
ControlFlow :: Continue ( elem) => elem,
879
879
} ;
880
880
881
- // SAFETY: `guard.initialized` starts at 0, is increased by one in the
882
- // loop and the loop is aborted once it reaches N (which is
883
- // `array.len()`).
881
+ // SAFETY: `guard.initialized` starts at 0, which means push can be called
882
+ // at most N times, which this loop does.
884
883
unsafe {
885
- guard. array_mut . get_unchecked_mut ( guard . initialized ) . write ( item) ;
884
+ guard. push_unchecked ( item) ;
886
885
}
887
- guard. initialized += 1 ;
888
886
}
889
887
None => {
890
888
let alive = 0 ..guard. initialized ;
@@ -902,11 +900,42 @@ where
902
900
Ok ( Try :: from_output ( output) )
903
901
}
904
902
903
+ /// Panic guard for incremental initialization of arrays.
904
+ ///
905
+ /// Disarm the guard with `mem::forget` once the array has been initialized.
906
+ ///
907
+ /// # Safety
908
+ ///
909
+ /// All write accesses to this structure are unsafe and must maintain a correct
910
+ /// count of `initialized` elements.
911
+ ///
912
+ /// To minimize indirection fields are still pub but callers should at least use
913
+ /// `push_unchecked` to signal that something unsafe is going on.
905
914
pub ( crate ) struct Guard < ' a , T , const N : usize > {
915
+ /// The array to be initialized.
906
916
pub array_mut : & ' a mut [ MaybeUninit < T > ; N ] ,
917
+ /// The number of items that have been initialized so far.
907
918
pub initialized : usize ,
908
919
}
909
920
921
+ impl < T , const N : usize > Guard < ' _ , T , N > {
922
+ /// Adds an item to the array and updates the initialized item counter.
923
+ ///
924
+ /// # Safety
925
+ ///
926
+ /// No more than N elements must be initialized.
927
+ #[ inline]
928
+ pub unsafe fn push_unchecked ( & mut self , item : T ) {
929
+ // SAFETY: If `initialized` was correct before and the caller does not
930
+ // invoke this method more than N times then writes will be in-bounds
931
+ // and slots will not be initialized more than once.
932
+ unsafe {
933
+ self . array_mut . get_unchecked_mut ( self . initialized ) . write ( item) ;
934
+ self . initialized = self . initialized . unchecked_add ( 1 ) ;
935
+ }
936
+ }
937
+ }
938
+
910
939
impl < T , const N : usize > Drop for Guard < ' _ , T , N > {
911
940
fn drop ( & mut self ) {
912
941
debug_assert ! ( self . initialized <= N ) ;
0 commit comments