rust/library/core/src
bors 6c943bad02 Auto merge of #99541 - timvermeulen:flatten_cleanup, r=the8472
Refactor iteration logic in the `Flatten` and `FlatMap` iterators

The `Flatten` and `FlatMap` iterators both delegate to `FlattenCompat`:
```rust
struct FlattenCompat<I, U> {
    iter: Fuse<I>,
    frontiter: Option<U>,
    backiter: Option<U>,
}
```
Every individual iterator method that `FlattenCompat` implements needs to carefully manage this state, checking whether the `frontiter` and `backiter` are present, and storing the current iterator appropriately if iteration is aborted. This has led to methods such as `next`, `advance_by`, and `try_fold` all having similar code for managing the iterator's state.

I have extracted this common logic of iterating the inner iterators with the option to exit early into a `iter_try_fold` method:
```rust
impl<I, U> FlattenCompat<I, U>
where
    I: Iterator<Item: IntoIterator<IntoIter = U>>,
{
    fn iter_try_fold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
    where
        Fold: FnMut(Acc, &mut U) -> R,
        R: Try<Output = Acc>,
    { ... }
}
```
It passes each of the inner iterators to the given function as long as it keep succeeding. It takes care of managing `FlattenCompat`'s state, so that the actual `Iterator` methods don't need to. The resulting code that makes use of this abstraction is much more straightforward:
```rust
fn next(&mut self) -> Option<U::Item> {
    #[inline]
    fn next<U: Iterator>((): (), iter: &mut U) -> ControlFlow<U::Item> {
        match iter.next() {
            None => ControlFlow::CONTINUE,
            Some(x) => ControlFlow::Break(x),
        }
    }

    self.iter_try_fold((), next).break_value()
}
```
Note that despite being implemented in terms of `iter_try_fold`, `next` is still able to benefit from `U`'s `next` method. It therefore does not take the performance hit that implementing `next` directly in terms of `Self::try_fold` causes (in some benchmarks).

This PR also adds `iter_try_rfold` which captures the shared logic of `try_rfold` and `advance_back_by`, as well as `iter_fold` and `iter_rfold` for folding without early exits (used by `fold`, `rfold`, `count`, and `last`).

Benchmark results:
```
                                             before                after
bench_flat_map_sum                       423,255 ns/iter      414,338 ns/iter
bench_flat_map_ref_sum                 1,942,139 ns/iter    2,216,643 ns/iter
bench_flat_map_chain_sum               1,616,840 ns/iter    1,246,445 ns/iter
bench_flat_map_chain_ref_sum           4,348,110 ns/iter    3,574,775 ns/iter
bench_flat_map_chain_option_sum          780,037 ns/iter      780,679 ns/iter
bench_flat_map_chain_option_ref_sum    2,056,458 ns/iter      834,932 ns/iter
```

I added the last two benchmarks specifically to demonstrate an extreme case where `FlatMap::next` can benefit from custom internal iteration of the outer iterator, so take it with a grain of salt. We should probably do a perf run to see if the changes to `next` are worth it in practice.
2022-08-19 02:34:30 +00:00
..
alloc Rollup merge of #100030 - WaffleLapkin:nice_pointer_sis, r=scottmcm 2022-08-12 20:39:10 +05:30
array more typos 2022-08-11 07:37:22 -04:00
async_iter Add Stream alias for AsyncIterator 2022-03-15 20:59:13 -07:00
cell Move/rename lazy::{OnceCell, Lazy} to cell::{OnceCell, LazyCell} 2022-06-16 19:53:59 +04:00
char docs: remove repetition 2022-08-09 21:54:05 +00:00
convert Warn on unused doc(hidden) on trait impl items 2022-05-08 22:53:14 +02:00
ffi Inline CStr::from_bytes_with_nul_unchecked::rt_impl 2022-08-10 12:21:17 +00:00
fmt Adjust cfgs 2022-08-12 16:28:15 -04:00
future Stabilize future_poll_fn 2022-07-16 10:04:14 +09:00
hash Adjust cfgs 2022-08-12 16:28:15 -04:00
iter Auto merge of #99541 - timvermeulen:flatten_cleanup, r=the8472 2022-08-19 02:34:30 +00:00
macros Revert write! and writeln! to late drop temporaries 2022-07-24 11:12:00 -07:00
mem Adjust cfgs 2022-08-12 16:28:15 -04:00
num Rollup merge of #100661 - PunkyMunky64:patch-1, r=thomcc 2022-08-17 12:33:02 +02:00
ops Add map_continue and continue_value combinators to ControlFlow 2022-07-20 16:32:09 -04:00
panic Update integer_atomics tracking issue 2022-07-08 17:52:04 -04:00
prelude Create 2024 edition 2022-04-02 02:45:49 -04:00
ptr nicer Miri backtraces for from_exposed_addr 2022-08-13 12:55:43 -04:00
slice Adjust cfgs 2022-08-12 16:28:15 -04:00
str ascii -> ASCII in code comment 2022-08-05 18:45:42 +02:00
sync Adjust cfgs 2022-08-12 16:28:15 -04:00
task stabilize core::task::ready! 2022-07-18 16:04:52 +02:00
unicode revert changes to unicode stability 2022-07-08 21:18:15 +00:00
any.rs core::any: replace some unstable generic types with impl Trait 2022-07-05 15:06:31 +01:00
ascii.rs Inline <EscapeDefault as Iterator>::next 2022-03-10 15:35:22 +01:00
asserting.rs [RFC 2011] Library code 2022-05-22 07:18:32 -03:00
bool.rs Stabilize bool::then_some 2022-05-04 13:22:08 +02:00
borrow.rs
cell.rs adjust UnsafeCell documentation 2022-07-22 14:25:41 -04:00
clone.rs update cfg(bootstrap)s 2022-07-01 15:48:23 +02:00
cmp.rs Auto merge of #98655 - nnethercote:dont-derive-PartialEq-ne, r=dtolnay 2022-08-18 10:11:11 +00:00
default.rs Add documentation 2022-04-07 20:03:24 -04:00
hint.rs add miri-track-caller to some intrinsic-exposing methods 2022-07-24 14:49:33 -04:00
internal_macros.rs ignore a doctest for the non-exported macro 2022-05-03 18:33:56 +09:00
intrinsics.rs Adjust cfgs 2022-08-12 16:28:15 -04:00
lazy.rs Move/rename lazy::{OnceCell, Lazy} to cell::{OnceCell, LazyCell} 2022-06-16 19:53:59 +04:00
lib.rs Auto merge of #99182 - RalfJung:mitigate-uninit, r=scottmcm 2022-07-28 01:11:10 +00:00
marker.rs docs: show Clone and Copy on () doc pages 2022-06-07 12:12:49 -07:00
option.rs Fix links in std/core documentation 2022-07-05 21:33:39 +02:00
panic.rs resolve the conflict in compiler/rustc_session/src/parse.rs 2022-03-16 20:12:30 +08:00
panicking.rs trivial cfg(bootstrap) changes 2022-04-05 23:18:40 +02:00
pin.rs Fix the generator example for pin!() 2022-05-05 09:58:13 +10:00
primitive_docs.rs Adjust cfgs 2022-08-12 16:28:15 -04:00
primitive.rs
result.rs add same warning to Result::expect as Result::unwrap 2022-07-21 18:15:24 -06:00
time.rs Rollup merge of #100353 - theli-ua:master, r=joshtriplett 2022-08-10 09:28:23 -07:00
tuple.rs Adjust cfgs 2022-08-12 16:28:15 -04:00
unit.rs Use implicit capture syntax in format_args 2022-03-10 10:23:40 -05:00