Skip to content

Commit f8fd06f

Browse files
Rollup merge of rust-lang#159963 - Lfan-ke:feature/step-by-fused-iterator, r=jhpratt,dtolnay
core: implement FusedIterator for StepBy Implements the accepted ACP rust-lang/libs-team#757. `StepBy` yields no more items once its underlying iterator is exhausted, so it is fused whenever the underlying iterator is fused. `StepBy` was added in 1.28.0, just after the batch of `FusedIterator` impls stabilized in 1.26.0 (`Map`, `Skip`, `Take`, `Enumerate`, ...), so it was left out. ```rust impl<I: FusedIterator> FusedIterator for StepBy<I> {} ``` This is insta-stable, matching the sibling adapter impls, so it needs a libs-api FCP. Motivation from the ACP: crates with traits refined on top of `FusedIterator` (e.g. `range-set-blaze`'s `SortedStarts`) cannot cover `StepBy` today, even though it would always be valid. A `test_step_by_fused` regression test is added.
2 parents 2fb4ed8 + 0485003 commit f8fd06f

2 files changed

Lines changed: 19 additions & 1 deletion

File tree

library/core/src/iter/adapters/step_by.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::intrinsics;
2-
use crate::iter::{TrustedLen, TrustedRandomAccess, from_fn};
2+
use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, from_fn};
33
use crate::num::NonZero;
44
use crate::ops::{Range, Try};
55
use crate::range::RangeIter;
@@ -136,6 +136,11 @@ where
136136
#[stable(feature = "iterator_step_by", since = "1.28.0")]
137137
impl<I> ExactSizeIterator for StepBy<I> where I: ExactSizeIterator {}
138138

139+
// StepBy stops yielding items once the underlying iterator does, so it is fused
140+
// whenever the underlying iterator is fused.
141+
#[stable(feature = "step_by_fused", since = "CURRENT_RUSTC_VERSION")]
142+
impl<I> FusedIterator for StepBy<I> where I: FusedIterator {}
143+
139144
// SAFETY: This adapter is shortening. TrustedLen requires the upper bound to be calculated correctly.
140145
// These requirements can only be satisfied when the upper bound of the inner iterator's upper
141146
// bound is never `None`. I: TrustedRandomAccess happens to provide this guarantee while

library/coretests/tests/iter/adapters/step_by.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,3 +418,16 @@ fn test_step_by_nth_non_fused_on_non_first_take() {
418418
// so we should expect `StepBy::nth` to return `None`
419419
assert_eq!(iter.nth(usize::MAX), None)
420420
}
421+
422+
#[test]
423+
fn test_step_by_fused() {
424+
// `StepBy` is fused whenever the underlying iterator is fused.
425+
fn assert_fused<I: FusedIterator>(_: I) {}
426+
assert_fused((0..10).step_by(3));
427+
428+
// Once the underlying fused iterator is exhausted, `StepBy` keeps yielding `None`.
429+
let mut it = (0..3).step_by(5);
430+
assert_eq!(it.next(), Some(0));
431+
assert_eq!(it.next(), None);
432+
assert_eq!(it.next(), None);
433+
}

0 commit comments

Comments
 (0)