Skip to content

Zip's __iterator_get_unchecked doesn't preserve side-effects #82303

Closed as not planned

Description

I tried this code:

fn main() {
    let a = vec![String::new(), String::new()];
    let b = [()];
    
    let mut counter = 0;
    
    a.into_iter() 
        .map(|i| {
            counter += 1;
            i
        })
        .zip(&b)
        .zip(&b)
        .for_each(drop);
        
    assert_eq!(counter, 2);
    
    let a = vec![String::new(), String::new()];
    let b = [()];
    
    let mut counter = 0;
    
    a.iter()
        .map(|i| {
            counter += 1;
            i
        })
        .zip(&b)
        .zip(&b)
        .for_each(drop);
        
    assert_eq!(counter, 2); // this fails, even though it succeed in the non-specialized version
}

Playground link

I would expect the two iterators to behave the same, so either both asserts fail (actually the first should stop the program) or neither of them. Instead, the second iterator doesn't preserve side-effects. causing the second assert (and only that one) to fail.

I don't think there's a way to solve this without completly changing the TrustedRandomAccess trait to use some type level trickery to replace may_have_side_effect. I wonder if there's even a point to keep the simulated side effects in the specialized ZipImpl::next if it doesn't cover all cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    C-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