rust/library/core/tests
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
..
fmt
hash libcore tests: avoid int2ptr casts 2022-06-27 13:30:44 -04:00
iter Auto merge of #99541 - timvermeulen:flatten_cleanup, r=the8472 2022-08-19 02:34:30 +00:00
num Rename integer log* methods to ilog* 2022-08-09 10:20:49 -07:00
ops
alloc.rs Re-optimize Layout::array 2022-07-13 17:07:41 -07:00
any.rs core::any: replace some unstable generic types with impl Trait 2022-07-05 15:06:31 +01:00
array.rs Stabilize core::array::from_fn 2022-05-20 11:04:13 -03:00
ascii.rs
asserting.rs [RFC 2011] Library code 2022-05-22 07:18:32 -03:00
atomic.rs Rename AtomicPtr::fetch_{add,sub}{,_bytes} 2022-07-01 06:21:19 -07:00
bool.rs
cell.rs Fix Display for cell::{Ref,RefMut} 2022-05-20 11:16:30 -07:00
char.rs Debug print char 0 as '\0' rather than '\u{0}' 2022-03-27 04:49:10 -07:00
clone.rs Use Box::new() instead of box syntax in core tests 2022-05-29 01:44:11 +02:00
cmp.rs
const_ptr.rs cleanup code w/ pointers in std a little 2022-08-05 16:47:49 +04:00
convert.rs
future.rs
intrinsics.rs
lazy.rs Move/rename lazy::{OnceCell, Lazy} to cell::{OnceCell, LazyCell} 2022-06-16 19:53:59 +04:00
lib.rs Rollup merge of #100026 - WaffleLapkin:array-chunks, r=scottmcm 2022-08-14 17:09:14 +05:30
macros.rs
manually_drop.rs
mem.rs Add size assert in transmute_copy 2022-07-03 10:46:20 +01:00
nonzero.rs
ops.rs
option.rs Use Box::new() instead of box syntax in core tests 2022-05-29 01:44:11 +02:00
pattern.rs
pin_macro.rs
pin.rs
ptr.rs Auto merge of #98866 - nagisa:nagisa/align-offset-wroom, r=Mark-Simulacrum 2022-07-16 23:28:28 +00:00
result.rs Use Box::new() instead of box syntax in core tests 2022-05-29 01:44:11 +02:00
simd.rs Introduce core::simd trait imports in tests 2022-07-20 18:08:20 -07:00
slice.rs actually call assert_send_and_sync 2022-08-03 12:44:21 -04:00
str_lossy.rs
str.rs
task.rs
time.rs
tuple.rs
unicode.rs revert changes to unicode stability 2022-07-08 21:18:15 +00:00
waker.rs libcore tests: avoid int2ptr casts 2022-06-27 13:30:44 -04:00