Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nth_back() for Zip returns wrong values #68536

Closed
JohnTitor opened this issue Jan 25, 2020 · 8 comments · Fixed by #73565
Closed

nth_back() for Zip returns wrong values #68536

JohnTitor opened this issue Jan 25, 2020 · 8 comments · Fixed by #73565
Labels
A-iterators Area: Iterators C-bug Category: This is a bug. P-high High priority T-libs Relevant to the library team, which will review and decide on the PR/issue.

Comments

@JohnTitor
Copy link
Member

JohnTitor commented Jan 25, 2020

Assertions are successful in this code (playground):

let mut a = Vec::new();
let mut b = Vec::new();
let value = [1, 2, 3, 4, 5, 6]
    .iter()
    .cloned()
    .map(|n| {
        a.push(n);
        n * 10
    })
    .zip([2, 3, 4, 5, 6, 7, 8].iter().cloned().map(|n| {
        b.push(n * 100);
        n * 1000
    }))
    .nth_back(3);
assert_eq!(value, Some((30, 4000)));
assert_eq!(a, vec![6, 6, 5, 5, 4, 4, 3]);
assert_eq!(b, vec![800, 700, 700, 600, 600, 500, 500, 400]);

But later assertions are actually wrong (the second and third ones shouldn't double-count).
@matthewjasper pointed out it's a bug that exists in the current next_back implementation.

@JohnTitor JohnTitor added A-iterators Area: Iterators C-bug Category: This is a bug. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Jan 25, 2020
@timvermeulen
Copy link
Contributor

a and b are obviously wrong, but value seems correct to me? The zip produces

[(10, 2000), (20, 3000), (30, 4000), (40, 5000), (50, 6000), (60, 7000)]

so nth_back(3) correctly produces (30, 4000).

@JohnTitor
Copy link
Member Author

@timvermeulen Ah, my bad. Thanks for pointing out!

@timvermeulen
Copy link
Contributor

The problem seems to be that the specialized version of Zip::next_back calls TrustedRandomAccess::get_unchecked(i) on both inner iterators here, which doesn't affect the len() of the inner iterators in any way. As a result, the next time next_back is called, next_back is called on both inner iterators here because their length now exceeds self.len by 1. So I think we probably need to call next_back on the inner iterators instead of get_unchecked. I'll check if this negatively affects benchmarks in any way.

To be honest, it's not really clear to me why Zip needs get_unchecked anyway (or why Zip has the index and len fields for that matter). From quickly reading the code, it seems like its main purpose is to make Zip::nth O(1) in case both inner iterators are known to not have side-effects, but in that case I think we could just call nth on the inner iterators instead? Maybe I'm missing something.

@spastorino
Copy link
Member

This is really a libs-impl thing, fixing labels accordingly.

@spastorino spastorino added T-libs Relevant to the library team, which will review and decide on the PR/issue. and removed T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels May 14, 2020
@nikomatsakis
Copy link
Contributor

@timvermeulen did you ever experiment with the fix that it sounds like you had in mind here:

I'll check if this negatively affects benchmarks in any way.

@spastorino
Copy link
Member

Removing nomination as it was discussed during today's weekly meeting.

@spastorino spastorino added I-prioritize Issue: Indicates that prioritization has been requested for this issue. and removed I-nominated labels Jun 11, 2020
@Dylan-DPC-zz
Copy link

Marking this as p-high as per the prioritization discussion

@Dylan-DPC-zz Dylan-DPC-zz added P-high High priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Jun 14, 2020
@timvermeulen
Copy link
Contributor

@nikomatsakis Thanks for pinging me, I had completely forgotten about this. I remember going down a rabbit hole that eventually spawned #69187 — in a world where that compiled better, we might very well not need the index and len fields on Zip anymore (or, for that matter, a get_unchecked method that doesn't advance the iterator). But for now it looks like this issue is being taken care of.

@bors bors closed this as completed in d9d4d39 Aug 21, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-iterators Area: Iterators C-bug Category: This is a bug. P-high High priority T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants