1
1
use crate :: fmt;
2
2
use crate :: iter:: { FusedIterator , TrustedLen , UncheckedIterator } ;
3
- use crate :: mem:: { self , MaybeUninit } ;
3
+ use crate :: mem:: MaybeUninit ;
4
4
use crate :: num:: NonZero ;
5
+ use crate :: ops:: { NeverShortCircuit , Try } ;
5
6
6
7
/// Creates a new iterator that repeats a single element a given number of times.
7
8
///
@@ -95,10 +96,10 @@ impl<A> RepeatN<A> {
95
96
fn take_element ( & mut self ) -> Option < A > {
96
97
if self . count > 0 {
97
98
self . count = 0 ;
98
- let element = mem:: replace ( & mut self . element , MaybeUninit :: uninit ( ) ) ;
99
99
// SAFETY: We just set count to zero so it won't be dropped again,
100
100
// 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)
102
103
} else {
103
104
None
104
105
}
@@ -169,6 +170,39 @@ impl<A: Clone> Iterator for RepeatN<A> {
169
170
}
170
171
}
171
172
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
+
172
206
#[ inline]
173
207
fn last ( mut self ) -> Option < A > {
174
208
self . take_element ( )
@@ -203,6 +237,23 @@ impl<A: Clone> DoubleEndedIterator for RepeatN<A> {
203
237
fn nth_back ( & mut self , n : usize ) -> Option < A > {
204
238
self . nth ( n)
205
239
}
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
+ }
206
257
}
207
258
208
259
#[ stable( feature = "iter_repeat_n" , since = "1.82.0" ) ]
@@ -220,7 +271,7 @@ impl<A: Clone> UncheckedIterator for RepeatN<A> {
220
271
// SAFETY: the check above ensured that the count used to be non-zero,
221
272
// so element hasn't been dropped yet, and we just lowered the count to
222
273
// 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 ( ) }
224
275
} else {
225
276
// SAFETY: the count is non-zero, so it must have not been dropped yet.
226
277
let element = unsafe { self . element . assume_init_ref ( ) } ;
0 commit comments