Add Iterator::find_map
I'd like to propose to add `find_map` method to the `Iterator`: an occasionally useful utility, which relates to `filter_map` in the same way that `find` relates to `filter`.
`find_map` takes an `Option`-returning function, applies it to the elements of the iterator, and returns the first non-`None` result. In other words, `find_map(f) == filter_map(f).next()`.
Why do we want to add a function to the `Iterator`, which can be trivially expressed as a combination of existing ones? Observe that `find(f) == filter(f).next()`, so, by the same logic, `find` itself is unnecessary!
The more positive argument is that desugaring of `find[_map]` in terms of `filter[_map]().next()` is not super obvious, because the `filter` operation reads as if it is applies to the whole collection, although in reality we are interested only in the first element. That is, the jump from "I need a **single** result" to "let's use a function which maps **many** values to **many** values" is a non-trivial speed-bump, and causes friction when reading and writing code.
Does the need for `find_map` arise in practice? Yes!
* Anecdotally, I've more than once searched the docs for the function with `[T] -> (T -> Option<U>) -> Option<U>` signature.
* The direct cause for this PR was [this](https://github.com/rust-lang/cargo/pull/5187/files/1291c50e86ed4b31db0c76de03a47a5d0074bbd7#r174934173) discussion in Cargo, which boils down to "there's some pattern that we try to express here, but current approaches looks non-pretty" (and the pattern is `filter_map`
* There are several `filter_map().next` combos in Cargo: [[1]](545a4a2c93/src/cargo/ops/cargo_new.rs (L585)), [[2]](545a4a2c93/src/cargo/core/resolver/mod.rs (L1130)), [[3]](545a4a2c93/src/cargo/ops/cargo_rustc/mod.rs (L1086)).
* I've also needed similar functionality in `Kotlin` several times. There, it is expressed as `mapNotNull {}.firstOrNull`, as can be seen [here](ee8bdb4e07/src/main/kotlin/org/rust/cargo/project/model/impl/CargoProjectImpl.kt (L154)), [here](ee8bdb4e07/src/main/kotlin/org/rust/lang/core/resolve/ImplLookup.kt (L444)) [here](ee8bdb4e07/src/main/kotlin/org/rust/ide/inspections/RsLint.kt (L38)) and [here](ee8bdb4e07/src/main/kotlin/org/rust/cargo/toolchain/RustToolchain.kt (L74)) (and maybe in some other cases as well)
Note that it is definitely not among the most popular functions (it definitely is less popular than `find`), but, for example it (in case of Cargo) seems to be more popular than `rposition` (1 occurrence), `step_by` (zero occurrences) and `nth` (three occurrences as `nth(0)` which probably should be replaced with `next`).
Do we necessary need this function in `std`? Could we move it to itertools? That is possible, but observe that `filter`, `filter_map`, `find` and `find_map` together really form a complete table:
|||
|-------|---------|
| filter| find|
|filter_map|find_map|
It would be somewhat unsatisfying to have one quarter of this table live elsewhere :) Also, if `Itertools` adds an `find_map` method, it would be more difficult to move it to std due to name collision.
Hm, at this point I've searched for `filter_map` the umpteenth time, and, strangely, this time I do find this RFC: https://github.com/rust-lang/rfcs/issues/1801. I guess this could be an implementation though? :)
To sum up:
Pro:
- complete the symmetry with existing method
- codify a somewhat common non-obvious pattern
Contra:
- niche use case
- we can, and do, live without it
ef8804ba27 addressed #30170 by rejecting
huge alignments at the allocator API level, transforming a specific
platform bug/limitation into an enforced API limitation on all
platforms.
This change essentially reverts that commit, and instead makes alloc()
itself return AllocErr::Unsupported when receiving huge alignments.
This was discussed in https://github.com/rust-lang/rust/issues/32838#issuecomment-368348408
and following.
Implement some trivial size_hints for various iterators
This also implements ExactSizeIterator where applicable.
Addresses most of the Iterator traits mentioned in #23708.
I intend to do more, but I don't want to make the PR too large.
Chosen to start a precedent of using it on ones that are potentially-expensive and where using it for side effects is particularly discouraged.
Discuss :)
This adds a new method to all numeric `Atomic*` types with a
safe compare-and-set loop, so users will no longer need to write
their own, except in *very* strange circumstances.
This solves #48384 with `x.fetch_max(_)`/`x.fetch_min(_)`. It
also relates to #48655 (which I misuse as tracking issue for now).
*note* This *might* need a crater run because the functions could
clash with third party extension traits.
There are types that implement `Clone` and `Copy` but are not mentioned
in the documentation, because the implementations are provided by the
compiler. They are types of variants that cannot be fully covered by
trait implementations in Rust code, because the language is not
expressive enough.
Add implementations of `Clone` and `Copy` for some primitive types to
libcore so that they show up in the documentation. The concerned types
are the following:
* All primitive signed and unsigned integer types (`usize`, `u8`, `u16`,
`u32`, `u64`, `u128`, `isize`, `i8`, `i16`, `i32`, `i64`, `i128`);
* All primitive floating point types (`f32`, `f64`)
* `bool`
* `char`
* `!`
* Raw pointers (`*const T` and `*mut T`)
* Shared references (`&'a T`)
These types already implemented `Clone` and `Copy`, but the
implementation was provided by the compiler. The compiler no longer
provides these implementations and instead tries to look them up as
normal trait implementations. The goal of this change is to make the
implementations appear in the generated documentation.
For `Copy` specifically, the compiler would reject an attempt to write
an `impl` for the primitive types listed above with error `E0206`; this
error no longer occurs for these types, but it will still occur for the
other types that used to raise that error.
The trait implementations are guarded with `#[cfg(not(stage0))]` because
they are invalid according to the stage0 compiler. When the stage0
compiler is updated to a revision that includes this change, the
attribute will have to be removed, otherwise the stage0 build will fail
because the types mentioned above no longer implement `Clone` or `Copy`.
For type variants that are variadic, such as tuples and function
pointers, and for array types, the `Clone` and `Copy` implementations
are still provided by the compiler, because the language is not
expressive enough yet to be able to write the appropriate
implementations in Rust.
The initial plan was to add `impl` blocks guarded by `#[cfg(dox)]` to
make them apply only when generating documentation, without having to
touch the compiler. However, rustdoc's usage of the compiler still
rejected those `impl` blocks.
This is a [breaking-change] for users of `#![no_core]`, because they
will now have to supply their own implementations of `Clone` and `Copy`
for the primitive types listed above. The easiest way to do that is to
simply copy the implementations from `src/libcore/clone.rs` and
`src/libcore/marker.rs`.
Fixes#25893
Instead, expose apparently-fallible conversions in cases where
the implementation happens to be infallible for a given target.
Having an associated type / return type in a public API change
based on the target is a portability hazard.
Fix confusing doc for `scan`
The comment "the value passed on to the next iteration" confused me since it sounded more like what Haskell's [scanl](http://hackage.haskell.org/package/base-4.11.0.0/docs/Prelude.html#v:scanl) does where the closure's return value serves as both the "yielded value" *and* the new value of the "state".
I tried changing the example to make it clear that the closure's return value is decoupled from the state argument.