Bundle and document 6 BTreeMap navigation algorithms
- Expose a function to step through trees, without necessarily extracting the KV pair, that helps future operations like drain/retain (as demonstrated in [this drain_filter implementation](https://github.com/ssomers/rust/compare/btree_navigation_v3...ssomers:btree_drain_filter?expand=1))
- ~~Also aligns the implementation of the 2 x 3 iterators already using such navigation:~~
- ~~Delay the moment the K,V references are plucked from the tree, for the 4 iterators on immutable and owned maps, just for symmetry. The same had to be done to the two iterators for mutable maps in #58431.~~
- ~~Always explicitly use ptr::read to derive two handles from one handle. While the existing implementations for immutable maps (i.e. Range::next_unchecked and Range::next_back_unchecked) rely on implicit copying. There's no change in unsafe tags because these two functions were already (erroneously? prophetically?) tagged unsafe. I don't know whether they should be tagged unsafe. I guess they should be for mutable and owned maps, because you can change the map through one handle and leave the other handle invalid.~~
- Preserve the way two handles are (temporarily) derived from one handle: implementations for immutable maps (i.e. Range::next_unchecked and Range::next_back_unchecked) rely on copying (implicitly before, explicitly now) and the others do `ptr::read`.
- ~~I think the functions that support iterators on immutable trees (i.e. `Range::next_unchecked` and `Range::next_back_unchecked`) are erroneously tagged unsafe since you can already create multiple instances of such ranges, thus obtain multiple handles into the same tree. I did not change that but removed unsafe from the functions underneath.~~
Tested with miri in liballoc/tests/btree, except those that should_panic.
cargo benchcmp the best of 3 samples of all btree benchmarks before and after this PR:
```
name old1.txt ns/iter new2.txt ns/iter diff ns/iter diff % speedup
btree::map::find_rand_100 17 17 0 0.00% x 1.00
btree::map::find_rand_10_000 57 55 -2 -3.51% x 1.04
btree::map::find_seq_100 17 17 0 0.00% x 1.00
btree::map::find_seq_10_000 42 39 -3 -7.14% x 1.08
btree::map::first_and_last_0 14 14 0 0.00% x 1.00
btree::map::first_and_last_100 36 37 1 2.78% x 0.97
btree::map::first_and_last_10k 52 52 0 0.00% x 1.00
btree::map::insert_rand_100 34 34 0 0.00% x 1.00
btree::map::insert_rand_10_000 34 34 0 0.00% x 1.00
btree::map::insert_seq_100 46 46 0 0.00% x 1.00
btree::map::insert_seq_10_000 90 89 -1 -1.11% x 1.01
btree::map::iter_1000 2,811 2,771 -40 -1.42% x 1.01
btree::map::iter_100000 360,635 355,995 -4,640 -1.29% x 1.01
btree::map::iter_20 39 42 3 7.69% x 0.93
btree::map::iter_mut_1000 2,662 2,864 202 7.59% x 0.93
btree::map::iter_mut_100000 336,825 346,550 9,725 2.89% x 0.97
btree::map::iter_mut_20 40 43 3 7.50% x 0.93
btree::set::build_and_clear 4,184 3,994 -190 -4.54% x 1.05
btree::set::build_and_drop 4,151 3,976 -175 -4.22% x 1.04
btree::set::build_and_into_iter 4,196 4,155 -41 -0.98% x 1.01
btree::set::build_and_pop_all 5,176 5,241 65 1.26% x 0.99
btree::set::build_and_remove_all 6,868 6,903 35 0.51% x 0.99
btree::set::difference_random_100_vs_100 721 691 -30 -4.16% x 1.04
btree::set::difference_random_100_vs_10k 2,420 2,411 -9 -0.37% x 1.00
btree::set::difference_random_10k_vs_100 54,726 52,215 -2,511 -4.59% x 1.05
btree::set::difference_random_10k_vs_10k 164,384 170,256 5,872 3.57% x 0.97
btree::set::difference_staggered_100_vs_100 739 709 -30 -4.06% x 1.04
btree::set::difference_staggered_100_vs_10k 2,320 2,265 -55 -2.37% x 1.02
btree::set::difference_staggered_10k_vs_10k 68,020 70,246 2,226 3.27% x 0.97
btree::set::intersection_100_neg_vs_100_pos 23 24 1 4.35% x 0.96
btree::set::intersection_100_neg_vs_10k_pos 28 29 1 3.57% x 0.97
btree::set::intersection_100_pos_vs_100_neg 24 24 0 0.00% x 1.00
btree::set::intersection_100_pos_vs_10k_neg 28 28 0 0.00% x 1.00
btree::set::intersection_10k_neg_vs_100_pos 27 27 0 0.00% x 1.00
btree::set::intersection_10k_neg_vs_10k_pos 30 29 -1 -3.33% x 1.03
btree::set::intersection_10k_pos_vs_100_neg 27 28 1 3.70% x 0.96
btree::set::intersection_10k_pos_vs_10k_neg 29 29 0 0.00% x 1.00
btree::set::intersection_random_100_vs_100 592 572 -20 -3.38% x 1.03
btree::set::intersection_random_100_vs_10k 2,271 2,269 -2 -0.09% x 1.00
btree::set::intersection_random_10k_vs_100 2,301 2,333 32 1.39% x 0.99
btree::set::intersection_random_10k_vs_10k 147,879 150,148 2,269 1.53% x 0.98
btree::set::intersection_staggered_100_vs_100 622 632 10 1.61% x 0.98
btree::set::intersection_staggered_100_vs_10k 2,101 2,032 -69 -3.28% x 1.03
btree::set::intersection_staggered_10k_vs_10k 60,341 61,834 1,493 2.47% x 0.98
btree::set::is_subset_100_vs_100 417 426 9 2.16% x 0.98
btree::set::is_subset_100_vs_10k 1,281 1,324 43 3.36% x 0.97
btree::set::is_subset_10k_vs_100 2 2 0 0.00% x 1.00
btree::set::is_subset_10k_vs_10k 41,054 41,612 558 1.36% x 0.99
```
r? cuviper
Address inconsistency in using "is" with "declared here"
"is" was generally used for NLL diagnostics, but not other diagnostics. Using "is" makes the diagnostics sound more natural and readable, so it seems sensible to commit to them throughout.
r? @Centril
Shrink `Nonterminal`
These commits shrink `Nonterminal` from 240 bytes to 40 bytes. When building `serde_derive` they reduce the number of `memcpy` calls from 9.6M to 7.4M, and it's a tiny win on a few other benchmarks.
r? @petrochenkov
clarify "incorrect issue" error
Changes the message to be more precise, shrinks the span and adds a label specifying why the `issue` field is incorrect.
Change opt-level from 2 back to 3
In Cargo.toml, the opt-level for `release` and `bench` was overridden to be 2. This was to work around a problem with LLVM 7. However, rust no longer uses LLVM 7, so this is hopefully no longer needed?
I tried a little bit to replicate the original problem, and could not. I think running this through CI is the best way to smoke test this :) Even if things break dramatically, the comment should be updated to reflect that things are still broken with LLVM 9.
I'm just getting started playing with the compiler, so apologies if I've missed an obvious problem here.
fixes#52378
(possibly relevant is the [current update to LLVM 10](https://github.com/rust-lang/rust/pull/67759))
Add `Iterator::map_while`
In `Iterator` trait there is `*_map` version of [`filter`] — [`filter_map`], however, there is no `*_map` version of [`take_while`], that can also be useful.
### Use cases
In my code, I've found that I need to iterate through iterator of `Option`s, stopping on the first `None`. So I've written code like this:
```rust
let arr = [Some(4), Some(10), None, Some(3)];
let mut iter = arr.iter()
.take_while(|x| x.is_some())
.map(|x| x.unwrap());
assert_eq!(iter.next(), Some(4));
assert_eq!(iter.next(), Some(10));
assert_eq!(iter.next(), None);
assert_eq!(iter.next(), None);
```
Thit code
1) isn't clean
2) In theory, can generate bad bytecode (I'm actually **not** sure, but I think that `unwrap` would generate additional branches with `panic!`)
The same code, but with `map_while` (in the original PR message it was named "take_while_map"):
```rust
let arr = [Some(4), Some(10), None, Some(3)];
let mut iter = arr.iter().map_while(std::convert::identity);
```
Also, `map_while` can be useful when converting something (as in [examples]).
[`filter`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.filter
[`filter_map`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.filter_map
[`take_while`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.take_while
[examples]: https://github.com/rust-lang/rust/compare/master...WaffleLapkin:iter_take_while_map?expand=1#diff-7e57917f962fe6ffdfba51e4955ad6acR1042
In Cargo.toml, the opt-level for `release` and `bench` was
overridden to be 2. This was to work around a problem with LLVM
7. However, rust no longer uses LLVM 7, so this is no longer
needed.
This creates a small compile time regression in MIR constant eval,
so I've added a #[inline(always)] on the `step` function used in
const eval
Also creates a binary size increase in wasm-stringify-ints-small,
so I've bumped the limit there.
Move numeric consts to associated consts step1
A subset of #67913. Implements the first step of RFC https://github.com/rust-lang/rfcs/pull/2700
This PR adds the new constants as unstable constants and defines the old ones in terms of the new ones. Then fix a tiny bit of code that started having naming collisions because of the new assoc consts.
Removed a test that did not seem relevant any longer. Since doing just `u8::MIN` should now indeed be valid.
Document `From` implementation for NonZero nums
This is more of a nitpick than a real change in documentation. I did this for consistency with other documentation (namely Atomic integers).
Related to #51430
r? @steveklabnik
PS: I actually tested the code this time. My CPU died in the process, but I get to open a (hopefully 🤞) working PR
Document remaining undocumented `From` implementations for IPs
Some `From` implementations were missing documentation. I added examples, I tried to be as close to existing examples as possible.
Related to #51430 (cc @skade)
r? @steveklabnik
Use termize instead of term_size
`termize` is a fork of `term_size` which uses `winapi` 0.3 instead of 0.2. This is a step towards removing the `winapi` 0.2 dependency.
r? @Mark-Simulacrum
BTreeMap: tag and explain unsafe internal functions or assert preconditions
#68418 concluded that it's not desirable to tag all internal functions with preconditions as being unsafe. This PR does it to some functions, documents why, and elsewhere enforces the preconditions with asserts.
Implement clone_from for BTreeMap and BTreeSet
See #28481. This results in up to 90% speedups on simple data types when `self` and `other` are the same size, and is generally comparable or faster. Some concerns:
1. This implementation requires an `Ord` bound on the `Clone` implementation for `BTreeMap` and `BTreeSet`. Since these structs can only be created externally for keys with `Ord` implemented, this should be fine? If not, there's certainly a less safe way to do this.
2. Changing `next_unchecked` on `RangeMut` to return mutable key references allows for replacing the entire overlapping portion of both maps without changing the external interface in any way. However, if `clone_from` fails it can leave the `BTreeMap` in an invalid state, which might be unacceptable.
~This probably needs an FCP since it changes a trait bound, but (as far as I know?) that change cannot break any external code.~
This commit reduces the size of `Nonterminal` from a whopping 240 bytes
to 72 bytes (on x86-64), which gets it below the `memcpy` threshold.
It also removes some impedance mismatches with `Annotatable`, which
already uses `P` for these variants.
Rollup of 7 pull requests
Successful merges:
- #67722 (Minor: note how Any is an unsafe trait in SAFETY comments)
- #68586 (Make conflicting_repr_hints a deny-by-default c-future-compat lint)
- #68598 (Fix null synthetic_implementors error)
- #68603 (Changelog: Demonstrate final build-override syntax)
- #68609 (Set lld flavor for MSVC to link.exe)
- #68611 (Correct ICE caused by macros generating invalid spans.)
- #68627 (Document that write_all will not call write if given an empty buffer)
Failed merges:
r? @ghost
Document that write_all will not call write if given an empty buffer
Some types of Write instances have a semantic meaning associated with
writing an empty buffer, such as sending an empty packet. This works
when calling `write` directly, and supplying an empty buffer. However,
calling `write_all` on an empty buffer will simply never call `write`,
because `write_all` assumes it has no work to do.
Document this behavior, to help prospective users of
datagram-packet-style Write instances.