-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Fix bugs in Peekable and Flatten when using non-fused iterators #68915
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
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