11use crate :: {
22 intrinsics,
33 iter:: { from_fn, TrustedLen , TrustedRandomAccess } ,
4+ num:: NonZeroUsize ,
45 ops:: { Range , Try } ,
56} ;
67
@@ -22,7 +23,11 @@ pub struct StepBy<I> {
2223 /// Additionally this type-dependent preprocessing means specialized implementations
2324 /// cannot be used interchangeably.
2425 iter : I ,
25- step : usize ,
26+ /// This field is `step - 1`, aka the correct amount to pass to `nth` when iterating.
27+ /// It MUST NOT be `usize::MAX`, as `unsafe` code depends on being able to add one
28+ /// without the risk of overflow. (This is important so that length calculations
29+ /// don't need to check for division-by-zero, for example.)
30+ step_minus_one : usize ,
2631 first_take : bool ,
2732}
2833
@@ -31,7 +36,16 @@ impl<I> StepBy<I> {
3136 pub ( in crate :: iter) fn new ( iter : I , step : usize ) -> StepBy < I > {
3237 assert ! ( step != 0 ) ;
3338 let iter = <I as SpecRangeSetup < I > >:: setup ( iter, step) ;
34- StepBy { iter, step : step - 1 , first_take : true }
39+ StepBy { iter, step_minus_one : step - 1 , first_take : true }
40+ }
41+
42+ /// The `step` that was originally passed to `Iterator::step_by(step)`,
43+ /// aka `self.step_minus_one + 1`.
44+ #[ inline]
45+ fn original_step ( & self ) -> NonZeroUsize {
46+ // SAFETY: By type invariant, `step_minus_one` cannot be `MAX`, which
47+ // means the addition cannot overflow and the result cannot be zero.
48+ unsafe { NonZeroUsize :: new_unchecked ( intrinsics:: unchecked_add ( self . step_minus_one , 1 ) ) }
3549 }
3650}
3751
8195 // The zero-based index starting from the end of the iterator of the
8296 // last element. Used in the `DoubleEndedIterator` implementation.
8397 fn next_back_index ( & self ) -> usize {
84- let rem = self . iter . len ( ) % ( self . step + 1 ) ;
85- if self . first_take { if rem == 0 { self . step } else { rem - 1 } } else { rem }
98+ let rem = self . iter . len ( ) % self . original_step ( ) ;
99+ if self . first_take { if rem == 0 { self . step_minus_one } else { rem - 1 } } else { rem }
86100 }
87101}
88102
@@ -209,30 +223,30 @@ unsafe impl<I: Iterator> StepByImpl<I> for StepBy<I> {
209223
210224 #[ inline]
211225 default fn spec_next ( & mut self ) -> Option < I :: Item > {
212- let step_size = if self . first_take { 0 } else { self . step } ;
226+ let step_size = if self . first_take { 0 } else { self . step_minus_one } ;
213227 self . first_take = false ;
214228 self . iter . nth ( step_size)
215229 }
216230
217231 #[ inline]
218232 default fn spec_size_hint ( & self ) -> ( usize , Option < usize > ) {
219233 #[ inline]
220- fn first_size ( step : usize ) -> impl Fn ( usize ) -> usize {
221- move |n| if n == 0 { 0 } else { 1 + ( n - 1 ) / ( step + 1 ) }
234+ fn first_size ( step : NonZeroUsize ) -> impl Fn ( usize ) -> usize {
235+ move |n| if n == 0 { 0 } else { 1 + ( n - 1 ) / step }
222236 }
223237
224238 #[ inline]
225- fn other_size ( step : usize ) -> impl Fn ( usize ) -> usize {
226- move |n| n / ( step + 1 )
239+ fn other_size ( step : NonZeroUsize ) -> impl Fn ( usize ) -> usize {
240+ move |n| n / step
227241 }
228242
229243 let ( low, high) = self . iter . size_hint ( ) ;
230244
231245 if self . first_take {
232- let f = first_size ( self . step ) ;
246+ let f = first_size ( self . original_step ( ) ) ;
233247 ( f ( low) , high. map ( f) )
234248 } else {
235- let f = other_size ( self . step ) ;
249+ let f = other_size ( self . original_step ( ) ) ;
236250 ( f ( low) , high. map ( f) )
237251 }
238252 }
@@ -247,10 +261,9 @@ unsafe impl<I: Iterator> StepByImpl<I> for StepBy<I> {
247261 }
248262 n -= 1 ;
249263 }
250- // n and self.step are indices, we need to add 1 to get the amount of elements
264+ // n and self.step_minus_one are indices, we need to add 1 to get the amount of elements
251265 // When calling `.nth`, we need to subtract 1 again to convert back to an index
252- // step + 1 can't overflow because `.step_by` sets `self.step` to `step - 1`
253- let mut step = self . step + 1 ;
266+ let mut step = self . original_step ( ) . get ( ) ;
254267 // n + 1 could overflow
255268 // thus, if n is usize::MAX, instead of adding one, we call .nth(step)
256269 if n == usize:: MAX {
@@ -288,8 +301,11 @@ unsafe impl<I: Iterator> StepByImpl<I> for StepBy<I> {
288301 R : Try < Output = Acc > ,
289302 {
290303 #[ inline]
291- fn nth < I : Iterator > ( iter : & mut I , step : usize ) -> impl FnMut ( ) -> Option < I :: Item > + ' _ {
292- move || iter. nth ( step)
304+ fn nth < I : Iterator > (
305+ iter : & mut I ,
306+ step_minus_one : usize ,
307+ ) -> impl FnMut ( ) -> Option < I :: Item > + ' _ {
308+ move || iter. nth ( step_minus_one)
293309 }
294310
295311 if self . first_take {
@@ -299,16 +315,19 @@ unsafe impl<I: Iterator> StepByImpl<I> for StepBy<I> {
299315 Some ( x) => acc = f ( acc, x) ?,
300316 }
301317 }
302- from_fn ( nth ( & mut self . iter , self . step ) ) . try_fold ( acc, f)
318+ from_fn ( nth ( & mut self . iter , self . step_minus_one ) ) . try_fold ( acc, f)
303319 }
304320
305321 default fn spec_fold < Acc , F > ( mut self , mut acc : Acc , mut f : F ) -> Acc
306322 where
307323 F : FnMut ( Acc , Self :: Item ) -> Acc ,
308324 {
309325 #[ inline]
310- fn nth < I : Iterator > ( iter : & mut I , step : usize ) -> impl FnMut ( ) -> Option < I :: Item > + ' _ {
311- move || iter. nth ( step)
326+ fn nth < I : Iterator > (
327+ iter : & mut I ,
328+ step_minus_one : usize ,
329+ ) -> impl FnMut ( ) -> Option < I :: Item > + ' _ {
330+ move || iter. nth ( step_minus_one)
312331 }
313332
314333 if self . first_take {
@@ -318,7 +337,7 @@ unsafe impl<I: Iterator> StepByImpl<I> for StepBy<I> {
318337 Some ( x) => acc = f ( acc, x) ,
319338 }
320339 }
321- from_fn ( nth ( & mut self . iter , self . step ) ) . fold ( acc, f)
340+ from_fn ( nth ( & mut self . iter , self . step_minus_one ) ) . fold ( acc, f)
322341 }
323342}
324343
@@ -336,7 +355,7 @@ unsafe impl<I: DoubleEndedIterator + ExactSizeIterator> StepByBackImpl<I> for St
336355 // is out of bounds because the length of `self.iter` does not exceed
337356 // `usize::MAX` (because `I: ExactSizeIterator`) and `nth_back` is
338357 // zero-indexed
339- let n = n. saturating_mul ( self . step + 1 ) . saturating_add ( self . next_back_index ( ) ) ;
358+ let n = n. saturating_mul ( self . original_step ( ) . get ( ) ) . saturating_add ( self . next_back_index ( ) ) ;
340359 self . iter . nth_back ( n)
341360 }
342361
@@ -348,16 +367,16 @@ unsafe impl<I: DoubleEndedIterator + ExactSizeIterator> StepByBackImpl<I> for St
348367 #[ inline]
349368 fn nth_back < I : DoubleEndedIterator > (
350369 iter : & mut I ,
351- step : usize ,
370+ step_minus_one : usize ,
352371 ) -> impl FnMut ( ) -> Option < I :: Item > + ' _ {
353- move || iter. nth_back ( step )
372+ move || iter. nth_back ( step_minus_one )
354373 }
355374
356375 match self . next_back ( ) {
357376 None => try { init } ,
358377 Some ( x) => {
359378 let acc = f ( init, x) ?;
360- from_fn ( nth_back ( & mut self . iter , self . step ) ) . try_fold ( acc, f)
379+ from_fn ( nth_back ( & mut self . iter , self . step_minus_one ) ) . try_fold ( acc, f)
361380 }
362381 }
363382 }
@@ -371,16 +390,16 @@ unsafe impl<I: DoubleEndedIterator + ExactSizeIterator> StepByBackImpl<I> for St
371390 #[ inline]
372391 fn nth_back < I : DoubleEndedIterator > (
373392 iter : & mut I ,
374- step : usize ,
393+ step_minus_one : usize ,
375394 ) -> impl FnMut ( ) -> Option < I :: Item > + ' _ {
376- move || iter. nth_back ( step )
395+ move || iter. nth_back ( step_minus_one )
377396 }
378397
379398 match self . next_back ( ) {
380399 None => init,
381400 Some ( x) => {
382401 let acc = f ( init, x) ;
383- from_fn ( nth_back ( & mut self . iter , self . step ) ) . fold ( acc, f)
402+ from_fn ( nth_back ( & mut self . iter , self . step_minus_one ) ) . fold ( acc, f)
384403 }
385404 }
386405 }
@@ -424,8 +443,7 @@ macro_rules! spec_int_ranges {
424443 fn spec_next( & mut self ) -> Option <$t> {
425444 // if a step size larger than the type has been specified fall back to
426445 // t::MAX, in which case remaining will be at most 1.
427- // The `+ 1` can't overflow since the constructor substracted 1 from the original value.
428- let step = <$t>:: try_from( self . step + 1 ) . unwrap_or( <$t>:: MAX ) ;
446+ let step = <$t>:: try_from( self . original_step( ) . get( ) ) . unwrap_or( <$t>:: MAX ) ;
429447 let remaining = self . iter. end;
430448 if remaining > 0 {
431449 let val = self . iter. start;
@@ -474,7 +492,7 @@ macro_rules! spec_int_ranges {
474492 {
475493 // if a step size larger than the type has been specified fall back to
476494 // t::MAX, in which case remaining will be at most 1.
477- let step = <$t>:: try_from( self . step + 1 ) . unwrap_or( <$t>:: MAX ) ;
495+ let step = <$t>:: try_from( self . original_step ( ) . get ( ) ) . unwrap_or( <$t>:: MAX ) ;
478496 let remaining = self . iter. end;
479497 let mut acc = init;
480498 let mut val = self . iter. start;
@@ -500,7 +518,7 @@ macro_rules! spec_int_ranges_r {
500518 fn spec_next_back( & mut self ) -> Option <Self :: Item >
501519 where Range <$t>: DoubleEndedIterator + ExactSizeIterator ,
502520 {
503- let step = ( self . step + 1 ) as $t;
521+ let step = self . original_step ( ) . get ( ) as $t;
504522 let remaining = self . iter. end;
505523 if remaining > 0 {
506524 let start = self . iter. start;
0 commit comments