Random access impl of `Take::for_each`/`Take::fold` suppresses side effects of `next` call on empty iterator
Open
@Indrapal-70 is already working on this.
Since Aug 20, 2026.
A-docs
A-iterators
C-bug
T-libs
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
I tried this code:
use std::fmt::Debug;
fn main() {
eprintln!("does_print:");
consume(does_print());
eprintln!("does_not_print:");
consume(does_not_print());
}
fn does_not_print() -> impl Iterator<Item: Debug> {
[1, 2, 3].iter()
}
fn does_print() -> impl Iterator<Item: Debug> {
[1, 2, 3].iter().filter(|_| true) // use any noop adapter without `TrustedRandomAccessNoCoerce` here
}
fn consume(iter: impl Iterator<Item: Debug>) {
// the skip covers all the elements, meaning `take` is called on an empty iterator
iter.map(|it| dbg!(it)).skip(3).take(100).for_each(|_| {});
}
I expected to see this happen:
Either both iterations print, or neither does, since the only difference is that one iterator is being adapted with filter(true), which is a noop.
Instead, this happened:
does_print:
[src/main.rs:11:19] it = 1
[src/main.rs:11:19] it = 2
[src/main.rs:11:19] it = 3
does_not_print:
@rustbot label A-iterators T-libs
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.