Skip to content

Random access impl of Zip suppresses side effects of next on lhs if rhs is empty #161676

Description

@maxdexh

Similar to #161350, but with zip instead of take.

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 ExactSizeIterator<Item: Debug> + DoubleEndedIterator {
    [1, 2, 3].iter()
}
fn does_print() -> impl ExactSizeIterator<Item: Debug> + DoubleEndedIterator {
    [1, 2, 3].iter().inspect(|_| {}) // use any noop adapter without `TrustedRandomAccessNoCoerce` here
}

// all of the commented out methods have the same inconsistency
fn consume(iter: impl ExactSizeIterator<Item: Debug> + DoubleEndedIterator) {
    iter.map(|it| dbg!(it))
        .zip(([] as [i32; 0]).iter()) // zip with an empty random access iterator *on the right*
        .next();
//      .next_back();
//      .fold((), |(), _| ());
//      .nth(0);
}

The TrustedLen + !TrustedRandomAccessNoCoerce specialization for fold is also affected. Use std::iter::empty as the empty rhs iterator and replace inspect with filter(true) to see this.

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 inspect(|| {}), which is a noop.

Instead, this happened:

does_print:
[src/main.rs:19:19] it = 1
does_not_print:

@rustbot label A-iterators T-libs

Metadata

Metadata

Labels

A-iteratorsArea: IteratorsC-bugCategory: This is a bug.T-libsRelevant to the library team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions