This commit introduces 2 methods - `Option::zip` and `Option::zip_with` with
respective signatures:
- zip: `(Option<T>, Option<U>) -> Option<(T, U)>`
- zip_with: `(Option<T>, Option<U>, (T, U) -> R) -> Option<R>`
Both are under the feature gate "option_zip".
I'm not sure about the name "zip", maybe we can find a better name for this.
(I would prefer `union` for example, but this is a keyword :( )
--------------------------------------------------------------------------------
Recently in a russian rust begginers telegram chat a newbie asked (translated):
> Are there any methods for these conversions:
>
> 1. `(Option<A>, Option<B>) -> Option<(A, B)>`
> 2. `Vec<Option<T>> -> Option<Vec<T>>`
>
> ?
While second (2.) is clearly `vec.into_iter().collect::<Option<Vec<_>>()`, the
first one isn't that clear.
I couldn't find anything similar in the `core` and I've come to this solution:
```rust
let tuple: (Option<A>, Option<B>) = ...;
let res: Option<(A, B)> = tuple.0.and_then(|a| tuple.1.map(|b| (a, b)));
```
However this solution isn't "nice" (same for just `match`/`if let`), so I thought
that this functionality should be in `core`.
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
submodules: update clippy from 8485d40a to d556bb73
Changes:
````
rustup https://github.com/rust-lang/rust/pull/68944
rustup https://github.com/rust-lang/rust/pull/69589/
Rustup to rust-lang/rust#69076
Don't convert Path to lossy str
Use `into_path`
Use pattern matching instead of manually checking condition
Fix typo
Remove git2 dependency.
Document that wildcard_imports doesn't warn about `use ...::prelude::*;`
Change changelog formatting
Update changelog_update doc to reflect the actual ordering of the changelog
Update CHANGELOG.md
````
Fixes#70007
Rollup of 7 pull requests
Successful merges:
- #68746 (Make macro metavars respect (non-)hygiene)
- #69688 (Move tidy check to mingw-check)
- #69735 (bootstrap: Use hash to determine if sanitizers needs to be rebuilt)
- #69922 (implement zeroed and uninitialized with MaybeUninit)
- #69956 (Ensure HAS_FREE_LOCAL_NAMES is set for ReFree)
- #70061 (Cosmetic fixes in documentation)
- #70064 (Update books)
Failed merges:
r? @ghost
Ensure HAS_FREE_LOCAL_NAMES is set for ReFree
This fixes a bug introduced by #69469.
I don't have any ideas on how to reate a regression test for this.
bootstrap: Use hash to determine if sanitizers needs to be rebuilt
* Rebuild sanitizers runtimes when LLVM submodule commit changes.
* When rebuilding LLVM / sanitizers, remove the stamp file before
starting the build process to invalidate previous build output.
Rollup of 7 pull requests
Successful merges:
- #69811 (resolve: Print import chains on privacy errors)
- #69870 (expand: Implement something similar to `#[cfg(accessible(path))]`)
- #69881 (VariantSizeDifferences: bail on SizeOverflow)
- #70000 (resolve: Fix regression in resolution of raw keywords in paths)
- #70029 (Bump the bootstrap compiler)
- #70046 (Use sublice patterns to avoid computing the len)
- #70049 (Fiddle `ParamEnv` through to a place that used to use `ParamEnv::empty` in a buggy manner)
Failed merges:
r? @ghost
expand: Implement something similar to `#[cfg(accessible(path))]`
cc https://github.com/rust-lang/rust/issues/64797
The feature is implemented as a `#[cfg_accessible(path)]` attribute macro rather than as `#[cfg(accessible(path))]` because it needs to wait until `path` becomes resolvable, and `cfg` cannot wait, but macros can wait.
Later we can think about desugaring or not desugaring `#[cfg(accessible(path))]` into `#[cfg_accessible(path)]`.
This implementation is also incomplete in the sense that it never returns "false" from `cfg_accessible(path)`, it requires some tweaks to resolve, which is not quite ready to answer queries like this during early resolution.
However, the most important part of this PR is not `cfg_accessible` itself, but expansion infrastructure for retrying expansions.
Before this PR we could say "we cannot resolve this macro path, let's try it later", with this PR we can say "we cannot expand this macro, let's try it later" as well.
This is a pre-requisite for
- turning `#[derive(...)]` into a regular attribute macro,
- properly supporting eager expansion for macros that cannot yet be resolved like
```
fn main() {
println!(not_available_yet!());
}
macro_rules! make_available {
() => { #[macro_export] macro_rules! not_available_yet { () => { "Hello world!" } }}
}
make_available!();
```
Implement a feature for a sound specialization subset
This implements a new feature (`min_specialization`) that restricts specialization to a subset that is reasonable for the standard library to use.
The plan is to then:
* Update `libcore` and `liballoc` to compile with `min_specialization`.
* Add a lint to forbid use of `feature(specialization)` (and other unsound, type system extending features) in the standard library.
* Fix the soundness issues around `specialization`.
* Remove `min_specialization`
The rest of this is an overview from a comment in this PR
## Basic approach
To enforce this requirement on specializations we take the following approach:
1. Match up the substs for `impl2` so that the implemented trait and self-type match those for `impl1`.
2. Check for any direct use of `'static` in the substs of `impl2`.
3. Check that all of the generic parameters of `impl1` occur at most once in the *unconstrained* substs for `impl2`. A parameter is constrained if its value is completely determined by an associated type projection predicate.
4. Check that all predicates on `impl1` also exist on `impl2` (after matching substs).
## Example
Suppose we have the following always applicable impl:
```rust
impl<T> SpecExtend<T> for std::vec::IntoIter<T> { /* specialized impl */ }
impl<T, I: Iterator<Item=T>> SpecExtend<T> for I { /* default impl */ }
```
We get that the subst for `impl2` are `[T, std::vec::IntoIter<T>]`. `T` is constrained to be `<I as Iterator>::Item`, so we check only `std::vec::IntoIter<T>` for repeated parameters, which it doesn't have. The predicates of `impl1` are only `T: Sized`, which is also a predicate of impl2`. So this specialization is sound.
## Extensions
Unfortunately not all specializations in the standard library are allowed by this. So there are two extensions to these rules that allow specializing on some traits.
### rustc_specialization_trait
If a trait is always applicable, then it's sound to specialize on it. We check trait is always applicable in the same way as impls, except that step 4 is now "all predicates on `impl1` are always applicable". We require that `specialization` or `min_specialization` is enabled to implement these traits.
### rustc_specialization_marker
There are also some specialization on traits with no methods, including the `FusedIterator` trait which is advertised as allowing optimizations. We allow marking marker traits with an unstable attribute that means we ignore them in point 3 of the checks above. This is unsound but we allow it in the short term because it can't cause use after frees with purely safe code in the same way as specializing on traits methods can.
r? @nikomatsakis
cc #31844#67194
Changes:
````
rustup https://github.com/rust-lang/rust/pull/69738
rustup https://github.com/rust-lang/rust/pull/68944
Make use of `or_patterns` feature
rustup https://github.com/rust-lang/rust/pull/69589/
Rustup to rust-lang/rust#69076
Don't convert Path to lossy str
Use `into_path`
Use pattern matching instead of manually checking condition
Fix typo
Remove git2 dependency.
Document that wildcard_imports doesn't warn about `use ...::prelude::*;`
Change changelog formatting
Update changelog_update doc to reflect the actual ordering of the changelog
Update CHANGELOG.md
````
Fixes#70007
resolve/hygiene: `macro_rules` are not "legacy"
The "modern" vs "legacy" naming was introduced by jseyfried during initial implementation of macros 2.0.
At this point it's clear that `macro_rules` are not going anywhere and won't be deprecated in the near future.
So this PR changes the naming "legacy" (when it implies "macro_rules") to "macro_rules".
This should also help people reading this code because it's wasn't obvious that "legacy" actually meant "macro_rules" in these contexts.
The most contentious renaming here is probably
```
fn modern -> fn normalize_to_macros_2_0
fn modern_and_legacy -> fn normalize_to_macro_rules
```
Other alternatives that I could think of are `normalize_to_opaque`/`normalize_to_semitransparent`, or `strip_non_opaque`/`strip_transparent`, but they seemed less intuitive.
The documentation to these functions can be found in `symbol.rs`.
r? @matthewjasper
Refactor the `Qualif` trait
This PR attempts to preserve the existing semantics of the `Qualif` trait while reducing its API to two significant methods with descriptive names, `in_any_value_of_ty` and `in_adt_inherently`. The other `in_*` methods have been made into free functions, since they should never be overloaded. Finally, I changed the bounds on the `in_local` argument to be less restrictive (`FnMut` instead of `Fn`), which addresses a FIXME in the const-checker.
r? @eddyb
cc @pnkfelix @oli-obk
Rollup of 8 pull requests
Successful merges:
- #69686 (Use `pprust` to print attributes in rustdoc)
- #69858 (std: on Windows, use GetSystemTimePreciseAsFileTime if it is available)
- #69917 (Cleanup E0412 and E0422)
- #69964 (Add Node.js to PR CI image)
- #69992 (Block version-specific docs from search engines)
- #69995 (Add more context to the literal overflow message)
- #69998 (Add long error explanation for E0634)
- #70014 (Small fixes in rustdoc book)
Failed merges:
r? @ghost
Small fixes in rustdoc book
I read the `rustdoc` book today and noticed some small typos/problems. Mainly:
- `# fn foo() {}` was displayed when not needed because fenced block code type was `text` instead of `rust`;
- two path separators were missing and some Windows-style separators were not consistent with the rest of them (mainly Linux-style).
Here are my proposed fixes. It is my first PR for the rust project. Don't hesitate to tell me if I am doing it wrong or if you need anything else.
Have a nice day!