Skip to content

Incorrect FusedIterator implementation on TakeWhileInclusive #1088

@willchet

Description

@willchet

As it is currently implemented, TakeWhileInclusive is not a fused iterator if the underlying iterator is not also fused. A minimal example is at the bottom of this issue.

Here are some options as I see it:

  • Remove the FusedIterator implementation
  • Edit TakeWhileInclusive to make it fused, and document that this is a fused iterator
  • Edit the FusedIterator implementation to only apply when the underlying iterator is fused

Below is an example:

use itertools::Itertools;

fn main() {
    let my_iterator = MyIterator { counter: 0 };
    let mut take_while_inclusive = my_iterator.take_while_inclusive(|x| *x < 10);

    // This is okay...
    assert_eq!(take_while_inclusive.next(), None);
    assert_eq!(take_while_inclusive.next(), Some(2));
    assert_eq!(take_while_inclusive.next(), None);

    let my_iterator = MyIterator { counter: 0 };
    let mut fused = my_iterator.take_while_inclusive(|x| *x < 10).fuse();

    // ...but this is bad, since a fused iterator is returning Some after None
    assert_eq!(fused.next(), None);
    assert_eq!(fused.next(), Some(2));
    assert_eq!(fused.next(), None);
}

/// An iterator returning `None` for all odd numbers
struct MyIterator {
    counter: usize,
}

impl Iterator for MyIterator {
    type Item = usize;

    fn next(&mut self) -> Option<Self::Item> {
        self.counter += 1;

        if self.counter.is_multiple_of(2) {
            Some(self.counter)
        } else {
            None
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions