Fix bugs in Peekable and Flatten when using non-fused iterators#68915
Fix bugs in Peekable and Flatten when using non-fused iterators#68915bors merged 4 commits intorust-lang:masterfrom timvermeulen:non_fused_iter
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
PeekableandFlatten/FlatMapiterators when the underlying iterator isn't fused. For testing, I also added aNonFusediterator wrapper that panics whennextornext_backis called on an iterator that has returnedNonebefore, which will hopefully make it easier to spot these mistakes in the future.Peekable
Peekable::next_backwas implemented aswhich is incorrect because when the
peekedfield isSome(None), thenNonehas already been returned from the inner iterator and what it returns fromnext_backcan no longer be relied upon.test_peekable_non_fusedtests this.Flatten
When a
FlattenCompatinstance only has abackiterremaining (i.e.self.frontiterisNoneandself.iteris empty), thennextwill callself.iter.next()every time, so theiterfield 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_outertests this.Furthermore, previously
FlattenCompat::nextdid not setself.frontitertoNoneafter it returnedNone, which is incorrect when the inner iterator type isn't fused. I just delegated it totry_foldbecause that already handles it correctly.test_flatten_non_fused_innertests this.r? @scottmcm