Forward more ExactSizeIterator methods and `is_empty` edits
- Forward ExactSizeIterator methods in more places, like `&mut I` and `Box<I>` iterator impls.
- Improve `VecDeque::is_empty` itself (see commit 4)
- All the collections iterators now have `len` or `is_empty` forwarded if doing so is a benefit. In the remaining cases, they already use a simple size hint (using something like a stored `usize` value), which is sufficient for the default implementation of len and is_empty.
Remove Self: Sized from Iterator::nth
It is an unnecessary restriction; nth neither needs self to be sized
nor needs to be exempted from the trait object.
It increases the utility of the nth method, because type specific
implementations are available through `&mut I` or through an iterator
trait object.
It is a backwards compatible change due to the special cases of the
`where Self: Sized` bound; it was already optional to include this bound
in `Iterator` implementations.
It is an unnecessary restriction; nth neither needs self to be sized
nor needs to be exempted from the trait object.
It increases the utility of the nth method, because type specific
implementations are available through `&mut I` or through an iterator
trait object.
It is a backwards compatible change due to the special cases of the
`where Self: Sized` bound; it was already optional to include this bound
in `Iterator` implementations.
Fix two small issues in iterator docs
- `collect()` is a regular method, not an adaptor (does not return an Iterator). I just randomly picked `filter` as a third common adaptor to mention instead.
- Fix example in `Map`'s docs so that it uses the DoubleEndedIterator implementation
Forward ExactSizeIterator::len and is_empty for important iterator adaptors
Forward ExactSizeIterator::len and is_empty for important iterator adaptors
Because some iterators will provide improved version of len and/or is_empty,
adaptors should forward to those implementations if possible.
Peekable must remember if a None has been seen in the `.peek()` method.
It ensures that `.peek(); .peek();` or `.peek(); .next();` only advances the
underlying iterator at most once. This does not by itself make the iterator
fused.
Add impls for `&Wrapping`. Also `Sum`, `Product` impls for both `Wrapping` and `&Wrapping`.
There are two changes here (split into two commits):
- Ops for references to `&Wrapping` (`Add`, `Sub`, `Mul` etc.) similar to the way they are implemented for primitives.
- Impls for `iter::{Sum,Product}` for `Wrapping`.
As far as I know `impl` stability attributes don't really matter so I didn't bother breaking up the macro for two different kinds of stability. Happy to change if it does matter.
Add Iterator trait TrustedLen to enable better FromIterator / Extend
This trait attempts to improve FromIterator / Extend code by enabling it to trust the iterator to produce an exact number of elements, which means that reallocation needs to happen only once and is moved out of the loop.
`TrustedLen` differs from `ExactSizeIterator` in that it attempts to include _more_ iterators by allowing for the case that the iterator's len does not fit in `usize`. Consumers must check for this case (for example they could panic, since they can't allocate a collection of that size).
For example, chain can be TrustedLen and all numerical ranges can be TrustedLen. All they need to do is to report an exact size if it fits in `usize`, and `None` as the upper bound otherwise.
The trait describes its contract like this:
```
An iterator that reports an accurate length using size_hint.
The iterator reports a size hint where it is either exact
(lower bound is equal to upper bound), or the upper bound is `None`.
The upper bound must only be `None` if the actual iterator length is
larger than `usize::MAX`.
The iterator must produce exactly the number of elements it reported.
This trait must only be implemented when the contract is upheld.
Consumers of this trait must inspect `.size_hint()`’s upper bound.
```
Fixes#37232
Implement Iterator::fold for .chain(), .cloned(), .map() and the VecDeque iterators.
Chain can do something interesting here where it passes on the fold
into its inner iterators.
The lets the underlying iterator's custom fold() be used, and skips the
regular chain logic in next.
Also implement .fold() specifically for .map() and .cloned() so that any
inner fold improvements are available through map and cloned.
The same way, a VecDeque iterator fold can be turned into two slice folds.
These changes lend the power of the slice iterator's loop codegen to
VecDeque, and to chains of slice iterators, and so on.
It's an improvement for .sum() and .product(), and other uses of fold.
Chain can do something interesting here where it passes on the fold
into its inner iterators.
The lets the underlying iterator's custom fold() be used, and skips the
regular chain logic in next.
Implement .zip() specialization for Map and Cloned.
The crucial thing for transparent specialization is that we want to
preserve the potential side effects.
The simplest example is that in this code snippet:
`(0..6).map(f).zip((0..4).map(g)).count()`
`f` will be called five times, and `g` four times. The last time for `f`
is when the other iterator is at its end, so this element is unused.
This side effect can be preserved without disturbing code generation for
simple uses of `.map()`.
The `Zip::next_back()` case is even more complicated, unfortunately.
remove ExactSizeIterator from RangeInclusive<{u,i}{32,size}>
Fixes#36386.
This is a [breaking-change] for nightly users of `#![feature(inclusive_range_syntax)]` and/or `#![feature(inclusive_range)]`.
Remove data structure specialization for .zip() iterator
Go back on half the specialization, the part that changed the Zip
struct's fields themselves depending on the types of the iterators.
Previous PR: #33090
This means that the Zip iterator will always carry two usize fields,
which are sometimes unused. If a whole for loop using a .zip() iterator is
inlined, these are simply removed and have no effect.
The same improvement for Zip of for example slice iterators remain, and
they still optimize well. However, like when the specialization of zip
was merged, the compiler is still very sensistive to the exact context.
For example this code only autovectorizes if the function is used, not
if the code in zip_sum_i32 is inserted inline where it was called:
```rust
fn zip_sum_i32(xs: &[i32], ys: &[i32]) -> i32 {
let mut s = 0;
for (&x, &y) in xs.iter().zip(ys) {
s += x * y;
}
s
}
fn zipdot_i32_default_zip(b: &mut test::Bencher)
{
let xs = vec![1; 1024];
let ys = vec![1; 1024];
b.iter(|| {
zip_sum_i32(&xs, &ys)
})
}
```
Include a test that checks that `Zip<T, U>` is covariant w.r.t. T and U.
Fixes#35727
Go back on half the specialization, the part that changed the Zip
struct's fields themselves depending on the types of the iterators.
This means that the Zip iterator will always carry two usize fields,
which are unused. If a whole for loop using a .zip() iterator is
inlined, these are simply removed and have no effect.
The same improvement for Zip of for example slice iterators remain, and
they still optimize well. However, like when the specialization of zip
was merged, the compiler is still very sensistive to the exact context.
For example this code only autovectorizes if the function is used, not
if the code in zip_sum_i32 is inserted inline it was called:
```
fn zip_sum_i32(xs: &[i32], ys: &[i32]) -> i32 {
let mut s = 0;
for (&x, &y) in xs.iter().zip(ys) {
s += x * y;
}
s
}
fn zipdot_i32_default_zip(b: &mut test::Bencher)
{
let xs = vec![1; 1024];
let ys = vec![1; 1024];
b.iter(|| {
zip_sum_i32(&xs, &ys)
})
}
```
Include a test that checks that Zip<T, U> is covariant w.r.t. T and U.
Introduce max_by/min_by on iterators
See https://github.com/rust-lang/rfcs/issues/1722 for reference.
It seems that there is `min`, `max` (simple computation of min/max), `min_by_key`, `max_by_key` (min/max by comparing mapped values) but no `min_by` and `max_by` (min/max according to comparison function). However, e.g. on vectors or slices there is `sort`, `sort_by_key` and `sort_by`.
PR #35695 for `Range` was approved, so it seems that this side-effect-free style is preferred for Range* examples. This PR performs the same translation for `RangeFrom` and `RangeInclusive`. It also removes what looks to be an erroneously commented line for `#![feature(step_by)]`, and an unnecessary primitive-type annotation in `0u8..`.
add `fn main` wrappers to enable Rust Playground "Run" button