Skip to content

Behavior of Iterator::zip does not match with documentation when iterator is not fused #50225

Closed
@tirr-c

Description

@tirr-c

Iterator::zip says:

When either iterator returns None, all further calls to next will return None.

However, it is not always true; it actually returns Some after None when the source iterator is not fused.

/// An iterator that yields `None` every `p`-th call on `next`.
struct Foo {
    p: usize,
    c: usize,
}

impl Foo {
    fn new(p: usize) -> Self {
        Foo { p, c: 0 }
    }
}

impl Iterator for Foo {
    type Item = usize;
    
    fn next(&mut self) -> Option<usize> {
        self.c += 1;
        if self.c % self.p == 0 {
            None
        } else {
            Some(self.c)
        }
    }
}

fn main() {
    let a = Foo::new(3);
    let b = Foo::new(5);
    let mut c = a.zip(b);
    
    assert_eq!(c.next(), Some((1, 1)));
    assert_eq!(c.next(), Some((2, 2)));
    assert_eq!(c.next(), None);
    assert_eq!(c.next(), None);  // *
}
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `Some((4, 3))`,
 right: `None`', src/main.rs:34:5

Playground

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-docsArea: Documentation for any part of the project, including the compiler, standard library, and toolsC-enhancementCategory: An issue proposing an enhancement or a PR with one.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions