11use crate :: fmt;
22use crate :: iter:: { FusedIterator , TrustedLen , UncheckedIterator } ;
3- use crate :: mem:: { self , MaybeUninit } ;
3+ use crate :: mem:: MaybeUninit ;
44use crate :: num:: NonZero ;
5+ use crate :: ops:: { NeverShortCircuit , Try } ;
56
67/// Creates a new iterator that repeats a single element a given number of times.
78///
@@ -95,10 +96,10 @@ impl<A> RepeatN<A> {
9596 fn take_element ( & mut self ) -> Option < A > {
9697 if self . count > 0 {
9798 self . count = 0 ;
98- let element = mem:: replace ( & mut self . element , MaybeUninit :: uninit ( ) ) ;
9999 // SAFETY: We just set count to zero so it won't be dropped again,
100100 // and it used to be non-zero so it hasn't already been dropped.
101- unsafe { Some ( element. assume_init ( ) ) }
101+ let element = unsafe { self . element . assume_init_read ( ) } ;
102+ Some ( element)
102103 } else {
103104 None
104105 }
@@ -169,6 +170,39 @@ impl<A: Clone> Iterator for RepeatN<A> {
169170 }
170171 }
171172
173+ fn try_fold < B , F , R > ( & mut self , mut acc : B , mut f : F ) -> R
174+ where
175+ F : FnMut ( B , A ) -> R ,
176+ R : Try < Output = B > ,
177+ {
178+ if self . count > 0 {
179+ while self . count > 1 {
180+ self . count -= 1 ;
181+ // SAFETY: the count was larger than 1, so the element is
182+ // initialized and hasn't been dropped.
183+ acc = f ( acc, unsafe { self . element . assume_init_ref ( ) . clone ( ) } ) ?;
184+ }
185+
186+ // We could just set the count to zero directly, but doing it this
187+ // way should make it easier for the optimizer to fold this tail
188+ // into the loop when `clone()` is equivalent to copying.
189+ self . count -= 1 ;
190+ // SAFETY: we just set the count to zero from one, so the element
191+ // is still initialized, has not been dropped yet and will not be
192+ // accessed by future calls.
193+ f ( acc, unsafe { self . element . assume_init_read ( ) } )
194+ } else {
195+ try { acc }
196+ }
197+ }
198+
199+ fn fold < B , F > ( mut self , init : B , f : F ) -> B
200+ where
201+ F : FnMut ( B , A ) -> B ,
202+ {
203+ self . try_fold ( init, NeverShortCircuit :: wrap_mut_2 ( f) ) . 0
204+ }
205+
172206 #[ inline]
173207 fn last ( mut self ) -> Option < A > {
174208 self . take_element ( )
@@ -203,6 +237,23 @@ impl<A: Clone> DoubleEndedIterator for RepeatN<A> {
203237 fn nth_back ( & mut self , n : usize ) -> Option < A > {
204238 self . nth ( n)
205239 }
240+
241+ #[ inline]
242+ fn try_rfold < B , F , R > ( & mut self , init : B , f : F ) -> R
243+ where
244+ F : FnMut ( B , A ) -> R ,
245+ R : Try < Output = B > ,
246+ {
247+ self . try_fold ( init, f)
248+ }
249+
250+ #[ inline]
251+ fn rfold < B , F > ( self , init : B , f : F ) -> B
252+ where
253+ F : FnMut ( B , A ) -> B ,
254+ {
255+ self . fold ( init, f)
256+ }
206257}
207258
208259#[ stable( feature = "iter_repeat_n" , since = "1.82.0" ) ]
@@ -220,7 +271,7 @@ impl<A: Clone> UncheckedIterator for RepeatN<A> {
220271 // SAFETY: the check above ensured that the count used to be non-zero,
221272 // so element hasn't been dropped yet, and we just lowered the count to
222273 // zero so it won't be dropped later, and thus it's okay to take it here.
223- unsafe { mem :: replace ( & mut self . element , MaybeUninit :: uninit ( ) ) . assume_init ( ) }
274+ unsafe { self . element . assume_init_read ( ) }
224275 } else {
225276 // SAFETY: the count is non-zero, so it must have not been dropped yet.
226277 let element = unsafe { self . element . assume_init_ref ( ) } ;
0 commit comments