-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Fix bugs in Peekable and Flatten when using non-fused iterators #68915
Conversation
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
r? @Amanieu |
I am concerned that the generated code is now substantially more complicated. Wouldn't it have been better to simply set All the other changes look fine. |
Ping from triage: |
Sorry, yep, I'll address them soon. |
@Amanieu Thanks for taking a look! I assumed that the generated code for |
@bors r+ |
📌 Commit 8cf33b0 has been approved by |
Fix bugs in Peekable and Flatten when using non-fused iterators I fixed a couple of bugs with regard to the `Peekable` and `Flatten`/`FlatMap` iterators when the underlying iterator isn't fused. For testing, I also added a `NonFused` iterator wrapper that panics when `next` or `next_back` is called on an iterator that has returned `None` before, which will hopefully make it easier to spot these mistakes in the future. ### Peekable `Peekable::next_back` was implemented as ```rust self.iter.next_back().or_else(|| self.peeked.take().and_then(|x| x)) ``` which is incorrect because when the `peeked` field is `Some(None)`, then `None` has already been returned from the inner iterator and what it returns from `next_back` can no longer be relied upon. `test_peekable_non_fused` tests this. ### Flatten When a `FlattenCompat` instance only has a `backiter` remaining (i.e. `self.frontiter` is `None` and `self.iter` is empty), then `next` will call `self.iter.next()` every time, so the `iter` field needs to be fused. I fixed it by giving it the type `Fuse<I>` instead of `I`, I think this is the only way to fix it. `test_flatten_non_fused_outer` tests this. Furthermore, previously `FlattenCompat::next` did not set `self.frontiter` to `None` after it returned `None`, which is incorrect when the inner iterator type isn't fused. I just delegated it to `try_fold` because that already handles it correctly. `test_flatten_non_fused_inner` tests this. r? @scottmcm
☀️ Test successful - checks-azure |
Tested on commit rust-lang/rust@d939f70. Direct link to PR: <rust-lang/rust#68915> 💔 rls on linux: test-pass → test-fail (cc @Xanewok).
I fixed a couple of bugs with regard to the
Peekable
andFlatten
/FlatMap
iterators when the underlying iterator isn't fused. For testing, I also added aNonFused
iterator wrapper that panics whennext
ornext_back
is called on an iterator that has returnedNone
before, which will hopefully make it easier to spot these mistakes in the future.Peekable
Peekable::next_back
was implemented aswhich is incorrect because when the
peeked
field isSome(None)
, thenNone
has already been returned from the inner iterator and what it returns fromnext_back
can no longer be relied upon.test_peekable_non_fused
tests this.Flatten
When a
FlattenCompat
instance only has abackiter
remaining (i.e.self.frontiter
isNone
andself.iter
is empty), thennext
will callself.iter.next()
every time, so theiter
field needs to be fused. I fixed it by giving it the typeFuse<I>
instead ofI
, I think this is the only way to fix it.test_flatten_non_fused_outer
tests this.Furthermore, previously
FlattenCompat::next
did not setself.frontiter
toNone
after it returnedNone
, which is incorrect when the inner iterator type isn't fused. I just delegated it totry_fold
because that already handles it correctly.test_flatten_non_fused_inner
tests this.r? @scottmcm