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

Inconsistent Iterator::Cycle behavior on 1.7+ #13263

Closed
Andriamanitra opened this issue Apr 1, 2023 · 2 comments · Fixed by #13264
Closed

Inconsistent Iterator::Cycle behavior on 1.7+ #13263

Andriamanitra opened this issue Apr 1, 2023 · 2 comments · Fixed by #13264
Labels
kind:bug A bug in the code. Does not apply to documentation, specs, etc. kind:regression Something that used to correctly work but no longer works

Comments

@Andriamanitra
Copy link

Bug Report

When using the Enumerable#zip method with a cyclical iterator, the cycle gets stuck at the first element after exhausting the array once.

Minimal reproduction:

# this returns [1, 2, 3, 1, 2, 3, 1, 2, 3, 1] as expected
p! [1, 2, 3].cycle.first(10).to_a

# however with .zip([1, 2, 3].cycle) we get [1, 2, 3, 1, 1, 1, 1, 1, 1, 1]
p! (1..10).zip([1, 2, 3].cycle).map(&.last)

I ran into the issue on Crystal 1.7.3, and it still reproduces on master. I also tried 1.6.2 and 1.0.0, neither of which had the same issue.

@Andriamanitra Andriamanitra added the kind:bug A bug in the code. Does not apply to documentation, specs, etc. label Apr 1, 2023
@straight-shoota straight-shoota added the kind:regression Something that used to correctly work but no longer works label Apr 1, 2023
@Andriamanitra
Copy link
Author

After doing some bisecting I figured out the problem is caused by this change to the Object#not_nil! method (changing it back fixed the problem on master):

649f061#diff-07f037fc0bf516181a1b483763bdb95c0c959879bac83c1cc7b643e4d258ab4c

I'm not sure why that particular change would have such an effect though...

@HertzDevil
Copy link
Contributor

HertzDevil commented Apr 1, 2023

Apparently that PR makes not_nil! return a copy of the receiver when it is a struct:

iter = [1, 2, 3].cycle
iter.not_nil!.next # => 1
iter.not_nil!.next # => 2
iter.not_nil!.next # => 3
iter.not_nil!.next # => 1
iter.not_nil!.next # => 1
iter.not_nil!.next # => 1

Technically it would not be wrong either if iter.not_nil! returns a copy of iter, but we avoid this because #not_nil! is endowed with behavior specific to the method (contrast with #12846). Note that Iterator::CycleIterator should not be a struct in the first place.

This is still a possible codegen issue that might affect non-Iterator types; the issue itself exists all the way back to 1.0.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind:bug A bug in the code. Does not apply to documentation, specs, etc. kind:regression Something that used to correctly work but no longer works
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants