Skip to content

impl FusedIterator for Cycle<I> is incorrect  #90085

Open
@fee1-dead

Description

@fee1-dead

I tried this code on playground:

// Cycle implementation
/*
    fn next(&mut self) -> Option<<I as Iterator>::Item> {
        match self.iter.next() {
            None => {
                self.iter = self.orig.clone();
                self.iter.next()
            }
            y => y,
        }
    }
*/
use std::iter::FusedIterator;
use std::rc::Rc;
use std::cell::Cell;

pub struct ErraticIterator(Rc<Cell<usize>>, Option<()>);

impl Clone for ErraticIterator {
    fn clone(&self) -> ErraticIterator {
        self.0.set(self.0.get() + 1);
        
        Self(self.0.clone(), Some(()))
    }
}

impl Iterator for ErraticIterator {
    type Item = ();
    
    // Cycle behavior:
    //
    // Some(())
    // None -> .clone() -> None
    // Some(())
    // None -> .clone() -> None
    // ..
    fn next(&mut self) -> Option<()> {
        if self.0.get() % 2 == 0 {
            self.1.take()
        } else {
            None
        }
    }
}

pub fn fused_iter(it: &mut impl FusedIterator<Item = ()>) {
    it.for_each(|()| {});
    
    assert!(it.next().is_none());
}

fn main() {
    let it = ErraticIterator(Rc::new(Cell::new(0)), Some(()));
    fused_iter(&mut it.cycle())
}

I expected to see this happen: Cycle<ErraticIterator> should not be fuse thus compilation should fail.

Instead, this happened: Cycle implements FusedIterator, so the assertion fails that should always pass for actually fused iterators.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-iteratorsArea: IteratorsC-bugCategory: This is a bug.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions