Avoid useless sift_down when std::collections::binary_heap::PeekMut is never mutably dereferenced
If `deref_mut` is never called then it's not possible for the element to be mutated without internal mutability, meaning there's no need to call `sift_down`.
This could be a little improvement in cases where you want to mutate the biggest element of the heap only if it satisfies a certain predicate that needs only read access to the element.
Move to intra-doc links in collections/vec_deque.rs and collections/vec_deque/drain.rs
Helps with #75080.
@rustbot modify labels: T-doc, A-intra-doc-links
Remove unused feature gates from library/ crates
Removes some unused feature gates from library crates. It's likely not a complete list as I only tested a subset for which it's more likely that it is unused.
Test and fix Send and Sync traits of BTreeMap artefacts
Fixes#76686.
I'm not quite sure what all this implies. E.g. comparing with the definitions for `NodeRef` in node.rs, maybe an extra bound `T: 'a` is useful for something. The test compiles on stable/beta (apart from `drain_filter`) so I bet `Sync` is equally desirable.
r? @Mark-Simulacrum
BTreeMap: wrap node's raw parent pointer in NonNull
Now that the other `*const` (root) is gone, seemed like a small step forward.
r? `@Mark-Simulacrum`
Add as_str() to string::Drain.
Vec's Drain recently [had its `.as_slice()` stabilized](https://github.com/rust-lang/rust/pull/72584), but String's Drain was still missing the analogous `.as_str()`. This adds that.
Also improves the Debug implementation, which now shows the remaining data instead of just `"Drain { .. }"`.
Add associated constant `BITS` to all integer types
Recently I've regularly come across this snippet (in a few different crates, including `core` and `std`):
```rust
std::mem::size_of<usize>() * 8
```
I think it's time for a `usize::BITS`.
BTreeMap: avoid slices even more
Epilogue to #73971: it seems the compiler is unable to realize that creating a slice and `get_unchecked`-ing one element is a simple fetch. So try to spell it out for the only remaining but often invoked case.
Also, the previous code doesn't seem fair game to me, using `get_unchecked` to reach beyond the end of a slice. Although the local function `slice_insert` also does that.
r? `@Mark-Simulacrum`
Add array_windows fn
This mimicks the functionality added by array_chunks, and implements a const-generic form of
`windows`. It makes egregious use of `unsafe`, but by necessity because the array must be
re-interpreted as a slice of arrays, and unlike array_chunks this cannot be done by casting the
original array once, since each time the index is advanced it needs to move one element, not
`N`.
I'm planning on adding more tests, but this should be good enough as a premise for the functionality.
Notably: should there be more functions overwritten for the iterator implementation/in general?
~~I've marked the issue as #74985 as there is no corresponding exact issue for `array_windows`, but it's based of off `array_chunks`.~~
Edit: See Issue #75027 created by @lcnr for tracking issue
~~Do not merge until I add more tests, please.~~
r? @lcnr
Updated issue to #75027
Update to rm oob access
And hopefully fix docs as well
Fixed naming conflict in test
Fix test which used 1-indexing
Nth starts from 0, woops
Fix a bunch of off by 1 errors
See https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=757b311987e3fae1ca47122969acda5a
Add even more off by 1 errors
And also write `next` and `next_back` in terms of `nth` and `nth_back`.
Run fmt
Fix forgetting to change fn name in test
add nth_back test & document unsafe
Remove as_ref().unwrap()
Documented occurrences of unsafe, noting what invariants are maintained
Fix liballoc test suite for Miri
Mostly, fix the regression introduced by https://github.com/rust-lang/rust/pull/75207 that caused slices (i.e., references) to be created to invalid memory or memory that has aliasing pointers that we want to keep valid. @dylni this changes the type of `check_range` to only require the length, not the full reference to the slice, which indeed is all the information this function requires.
Also reduce the size of a test introduced in https://github.com/rust-lang/rust/pull/70793 to make it not take 3 minutes in Miri.
This makes https://github.com/RalfJung/miri-test-libstd work again.
Detect overflow in proc_macro_server subspan
* Detect overflow in proc_macro_server subspan
* Add tests for overflow in Vec::drain
* Add tests for overflow in String / VecDeque operations using ranges
Optimize behavior of vec.split_off(0) (take all)
Optimization improvement to `split_off()` so the performance meets the
intuitively expected behavior when `at == 0`, avoiding the current behavior
of copying the entire vector.
The change honors documented behavior that the original vector's
"previous capacity unchanged".
This improvement better supports the pattern for building and flushing a
buffer of elements, such as the following:
```rust
let mut vec = Vec::new();
loop {
vec.push(something);
if condition_is_met {
process(vec.split_off(0));
}
}
```
`Option` wrapping is the first alternative I thought of, but is much
less obvious and more verbose:
```rust
let mut capacity = 1;
let mut vec: Option<Vec<Stuff>> = None;
loop {
vec.get_or_insert_with(|| Vec::with_capacity(capacity)).push(something);
if condition_is_met {
capacity = vec.capacity();
process(vec.take().unwrap());
}
}
```
Directly using `mem::replace()` (instead of calling`split_off()`) could work,
but `mem::replace()` is a more advanced tool for Rust developers, and in
this case, I believe developers would assume the standard library should
be sufficient for the purpose described here.
The benefit of the approach to this change is it does not change the
existing API contract, but improves the peformance of `split_off(0)` for
`Vec`, `String` (which delegates `split_off()` to `Vec`), and any other
existing use cases.
This change adds tests to validate the behavior of `split_off()` with
regard to capacity, as originally documented, and confirm that behavior
still holds, when `at == 0`.
The change is an implementation detail, and does not require a
documentation change, but documenting the new behavior as part of its
API contract may benefit future users.
(Let me know if I should make that documentation update.)
Note, for future consideration:
I think it would be helpful to introduce an additional method to `Vec`
(if not also to `String`):
```
pub fn take_all(&mut self) -> Self {
self.split_off(0)
}
```
This would make it more clear how `Vec` supports the pattern, and make
it easier to find, since the behavior is similar to other `take()`
methods in the Rust standard library.
r? `@wesleywiser`
FYI: `@tmandry`
Optimization improvement to `split_off()` so the performance meets the
intuitively expected behavior when `at == 0`, avoiding the current
behavior of copying the entire vector.
The change honors documented behavior that the method leaves the
original vector's "previous capacity unchanged".
This improvement better supports the pattern for building and flushing a
buffer of elements, such as the following:
```rust
let mut vec = Vec::new();
loop {
vec.push(something);
if condition_is_met {
process(vec.split_off(0));
}
}
```
`Option` wrapping is the first alternative I thought of, but is much
less obvious and more verbose:
```rust
let mut capacity = 1;
let mut vec: Option<Vec<Stuff>> = None;
loop {
vec.get_or_insert_with(|| Vec::with_capacity(capacity)).push(something);
if condition_is_met {
capacity = vec.capacity();
process(vec.take().unwrap());
}
}
```
Directly applying `mem::replace()` could work, but `mem::` functions are
typically a last resort, when a developer is actively seeking better
performance than the standard library provides, for example.
The benefit of the approach to this change is it does not change the
existing API contract, but improves the peformance of `split_off(0)` for
`Vec`, `String` (which delegates `split_off()` to `Vec`), and any other
existing use cases.
This change adds tests to validate the behavior of `split_off()` with
regard to capacity, as originally documented, and confirm that behavior
still holds, when `at == 0`.
The change is an implementation detail, and does not require a
documentation change, but documenting the new behavior as part of its
API contract may benefit future users.
(Let me know if I should make that documentation update.)
Note, for future consideration:
I think it would be helpful to introduce an additional method to `Vec`
(if not also to `String`):
```
pub fn take_all(&mut self) -> Self {
self.split_off(0)
}
```
This would make it more clear how `Vec` supports the pattern, and make
it easier to find, since the behavior is similar to other `take()`
methods in the Rust standard library.
Remove internal and unstable MaybeUninit::UNINIT.
Looks like it is no longer necessary, as `uninit_array()` can be used instead in the few cases where it was needed.
(I wanted to just add `#[doc(hidden)]` to remove clutter from the documentation, but looks like it can just be removed entirely.)
Warn for #[unstable] on trait impls when it has no effect.
Earlier today I sent a PR with an `#[unstable]` attribute on a trait `impl`, but was informed that this attribute has no effect there. (comment: https://github.com/rust-lang/rust/pull/76525#issuecomment-689678895, issue: https://github.com/rust-lang/rust/issues/55436)
This PR adds a warning for this situation. Trait `impl` blocks with `#[unstable]` where both the type and the trait are stable will result in a warning:
```
warning: An `#[unstable]` annotation here has no effect. See issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information.
--> library/std/src/panic.rs:235:1
|
235 | #[unstable(feature = "integer_atomics", issue = "32976")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
---
It detects three problems in the existing code:
1. A few `RefUnwindSafe` implementations for the atomic integer types in `library/std/src/panic.rs`. Example:
d92155bf6a/library/std/src/panic.rs (L235-L236)
2. An implementation of `Error` for `LayoutErr` in `library/std/srd/error.rs`:
d92155bf6a/library/std/src/error.rs (L392-L397)
3. `From` implementations for `Waker` and `RawWaker` in `library/alloc/src/task.rs`. Example:
d92155bf6a/library/alloc/src/task.rs (L36-L37)
Case 3 interesting: It has a bound with an `#[unstable]` trait (`W: Wake`), so appears to have much effect on stable code. It does however break similar blanket implementations. It would also have immediate effect if `Wake` was implemented for any stable type. (Which is not the case right now, but there are no warnings in place to prevent it.) Whether this case is a problem or not is not clear to me. If it isn't, adding a simple `c.visit_generics(..);` to this PR will stop the warning for this case.
Eliminate mut reference UB in Drop impl for Rc<T>
This changes `self.ptr.as_mut()` with `get_mut_unchecked` which
does not use an intermediate reference. Arc<T> already handled this
case properly.
Fixes#76509
Add `slice::array_chunks_mut`
This follows `array_chunks` from #74373 with a mutable version, `array_chunks_mut`. The implementation is identical apart from mutability. The new tests are adaptations of the `chunks_exact_mut` tests, plus an inference test like the one for `array_chunks`.
I reused the unstable feature `array_chunks` and tracking issue #74985, but I can separate that if desired.
r? `@withoutboats`
cc `@lcnr`
BTreeMap: move up reference to map's root from NodeRef
Since the introduction of `NodeRef` years ago, it also contained a mutable reference to the owner of the root node of the tree (somewhat disguised as *const). Its intent is to be used only when the rest of the `NodeRef` is no longer needed. Moving this to where it's actually used, thought me 2 things:
- Some sort of "postponed mutable reference" is required in most places that it is/was used, and that's exactly where we also need to store a reference to the length (number of elements) of the tree, for the same reason. The length reference can be a normal reference, because the tree code does not care about tree length (just length per node).
- It's downright obfuscation in `from_sorted_iter` (transplanted to #75329)
- It's one of the reasons for the scary notice on `reborrow_mut`, the other one being addressed in #73971.
This does repeat the raw pointer code in a few places, but it could be bundled up with the length reference.
r? `@Mark-Simulacrum`
This avoids overlapping a reference covering the data field,
which may be changed due in concurrent conditions. This fully
fixed the UB mainfested with `new_cyclic`.
Since trait implementations cannot be unstable, we should only add them
when the as_str feature gets stabilized. Until then, only `.as_str()` is
available (behind a feature gate).
Move various ui const tests to `library`
Move:
- `src\test\ui\consts\const-nonzero.rs` to `library\core`
- `src\test\ui\consts\ascii.rs` to `library\core`
- `src\test\ui\consts\cow-is-borrowed` to `library\alloc`
Part of #76268
r? @matklad
Move some Vec UI tests into alloc unit tests
A bit of work towards #76268, makes a number of the Vec UI tests that are simply running code into unit tests. Ensured that they are being run when testing liballoc locally.
rename MaybeUninit slice methods
The `first` methods conceptually point to the whole slice, not just its first element, so rename them to be consistent with the raw ptr methods on ref-slices.
Also, do the equivalent of https://github.com/rust-lang/rust/pull/76047 for the slice reference getters, and make them part of https://github.com/rust-lang/rust/issues/63569 (so far they somehow had no tracking issue).
* first_ptr -> slice_as_ptr
* first_ptr_mut -> slice_as_mut_ptr
* slice_get_ref -> slice_assume_init_ref
* slice_get_mut -> slice_assume_init_mut
BTreeMap: introduce marker::ValMut and reserve Mut for unique access
The mutable BTreeMap iterators (apart from `DrainFilter`) are double-ended, meaning they have to rely on a front and a back handle that each represent a reference into the tree. Reserve a type category `marker::ValMut` for them, so that we guarantee that they cannot reach operations on handles with borrow type `marker::Mut`and that these operations can assume unique access to the tree.
Including #75195, benchmarks report no genuine change:
```
benchcmp old new --threshold 5
name old ns/iter new ns/iter diff ns/iter diff % speedup
btree::map::iter_100 3,333 3,023 -310 -9.30% x 1.10
btree::map::range_unbounded_vs_iter 36,624 31,569 -5,055 -13.80% x 1.16
```
r? @Mark-Simulacrum
This is very similar to the existing `Box<[T; N]>: TryFrom<Box<[T]>>`, but allows avoiding the `shrink_to_fit` if you have a vector and not a boxed slice.
Move:
- `src\test\ui\consts\const-nonzero.rs` to `library\core`
- `src\test\ui\consts\ascii.rs` to `library\core`
- `src\test\ui\consts\cow-is-borrowed` to `library\alloc`
Part of #76268
The InPlaceIterable debug assert checks that the write pointer
did not advance beyond the read pointer. But TrustedRandomAccess
never advances the read pointer, thus triggering the assert.
Skip the assert if the source pointer did not change during iteration.
The optimization meant that every extend code path had to emit llvm
IR for from_iter and extend spec_extend, which likely impacts
compile times while only improving a few edge-cases
switch to try_fold and segregate the drop handling to keep
collect::<Vec<u8>>() and similar optimizer-friendly
It comes at the cost of less accurate debug_asserts and code complexity
Convert many files to intra-doc links
Helps with https://github.com/rust-lang/rust/issues/75080
r? @poliorcetics
I recommend reviewing one commit at a time, but the diff is small enough you can do it all at once if you like :)
- Use intra-doc links for `std::io` in `std::fs`
- Use intra-doc links for File::read in unix/ext/fs.rs
- Remove explicit intra-doc links for `true` in `net/addr.rs`
- Use intra-doc links in alloc/src/sync.rs
- Use intra-doc links in src/ascii.rs
- Switch to intra-doc links in alloc/rc.rs
- Use intra-doc links in core/pin.rs
- Use intra-doc links in std/prelude
- Use shorter links in `std/fs.rs`
`io` is already in scope.
`try_reserve` and `try_reserve_exact` docs refer to calling `reserve` and `reserve_exact`.
`try_reserve_exact` example uses `try_reserve` method instead of `try_reserve_exact`.
Make `cow_is_borrowed` methods const
Constify the following methods of `alloc::borrow::Cow`:
- `is_borrowed`
- `is_owned`
Analogous to the const methods `is_some` and `is_none` for Option, and `is_ok` and `is_err` for Result.
These methods are still unstable under `cow_is_borrowed`.
Possible because of #49146 (Allow if and match in constants).
Tracking issue: #65143
Constify the following methods of `alloc::borrow::Cow`:
- `is_borrowed`
- `is_owned`
These methods are still unstable under `cow_is_borrowed`.
Possible because of #49146 (Allow if and match in constants).
Tracking issue: #65143
Shorten liballoc doc intra link while readable
r? @jyn514
Do you want to reviews these sort of pull requests in the future? I might send a few of them while reading vec code.
Report an ambiguity if both modules and primitives are in scope for intra-doc links
Closes https://github.com/rust-lang/rust/issues/75381
- Add a new `prim@` disambiguator, since both modules and primitives are in the same namespace
- Refactor `report_ambiguity` into a closure
Additionally, I noticed that rustdoc would previously allow `[struct@char]` if `char` resolved to a primitive (not if it had a DefId). I fixed that and added a test case.
I also need to update libstd to use `prim@char` instead of `type@char`. If possible I would also like to refactor `ambiguity_error` to use `Disambiguator` instead of its own hand-rolled match - that ran into issues with `prim@` (I updated one and not the other) and it would be better for them to be in sync.
stabilize ptr_offset_from
This stabilizes ptr::offset_from, and closes https://github.com/rust-lang/rust/issues/41079. It also removes the deprecated `wrapping_offset_from`. This function was deprecated 19 days ago and was never stable; given an FCP of 10 days and some waiting time until FCP starts, that leaves at least a month between deprecation and removal which I think is fine for a nightly-only API.
Regarding the open questions in https://github.com/rust-lang/rust/issues/41079:
* Should offset_from abort instead of panic on ZSTs? -- As far as I know, there is no precedent for such aborts. We could, however, declare this UB. Given that the size is always known statically and the check thus rather cheap, UB seems excessive.
* Should there be more methods like this with different restrictions (to allow nuw/nsw, perhaps) or that return usize (like how isize-taking offset is more conveniently done with usize-taking add these days)? -- No reason to block stabilization on that, we can always add such methods later.
Also nominating the lang team because this exposes an intrinsic.
The stabilized method is best described [by its doc-comment](56d4b2d69a/src/libcore/ptr/const_ptr.rs (L227)). The documentation forgot to mention the requirement that both pointers must "have the same provenance", aka "be derived from pointers to the same allocation", which I am adding in this PR. This is a precondition that [Miri already implements](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=a3b9d0a07a01321f5202cd99e9613480) and that, should LLVM ever obtain a `psub` operation to subtract pointers, will likely be required for that operation (following the semantics in [this paper](https://people.mpi-sws.org/~jung/twinsem/twinsem.pdf)).
New zeroed slice
Add to #63291 the methods
```rust
impl<T> Box<[T]> { pub fn new_zeroed_slice(len: usize) -> Box<[MaybeUninit<T>]> {…} }
impl<T> Rc<[T]> { pub fn new_zeroed_slice(len: usize) -> Rc<[MaybeUninit<T>]> {…} }
impl<T> Arc<[T]> { pub fn new_zeroed_slice(len: usize) -> Arc<[MaybeUninit<T>]> {…} }
```
as suggested in https://github.com/rust-lang/rust/issues/63291#issuecomment-605511675 .
Also optimize `{Rc, Arc}::new_zeroed` to use `alloc_zeroed`, otherwise they are no more efficient than using `new_uninit` and zeroing the memory manually (which was the original implementation).
Move to intra-doc links for task.rs and vec.rs
Partial fix for #75080
links for [`get`], [`get_mut`] skipped due to #75643
link for [`copy_from_slice`] skipped due to #63351
Don't panic in Vec::shrink_to_fit
We can help the compiler see that `Vec::shrink_to_fit` will never reach the panic case in `RawVec::shrink_to_fit`, just by guarding the call only for cases where the capacity is strictly greater. A capacity less than the length is only possible through an unsafe call to `set_len`, which would break the `Vec` invariants, so `shrink_to_fit` can just ignore that.
This removes the panicking code from the examples in both #71861 and #75636.
Revert the fundamental changes in #74762 and #75257
Before possibly going over to #75487. Also contains some added and fixed comments.
r? @Mark-Simulacrum
Migrate unit tests of btree collections to their native breeding ground
There's one BTreeSet test case that I couldn't easily convince to come along, maybe because it truly is an integration test. But leaving it in place would mean git wouldn't see the move so I also moved it to a new file.
r? @Mark-Simulacrum
BTreeMap: purge innocent use of into_kv_mut
Replace the use of `into_kv_mut` into more precise calls. This makes more sense if you know that the single remaining use of `into_kv_mut` is in fact evil and can be trialled in court (#75200) and sent to a correction facility (#73971).
No real performance difference reported (but functions that might benefit a tiny constant bit like `BTreeMap::get_mut` aren't benchmarked):
```
benchcmp old new --threshold 5
name old ns/iter new ns/iter diff ns/iter diff % speedup
btree::map::clone_fat_100 63,073 59,256 -3,817 -6.05% x 1.06
btree::map::iter_100 3,514 3,235 -279 -7.94% x 1.09
```
Stop BTreeMap casts from reborrowing
Down in btree/node.rs, the interface and use of `cast_unchecked` look a bit shady. It's really just there for inverting `forget_type` which does not borrow. By borrowing we can't write the same `cast_unchecked` in the same way at the Handle level.
No change in undefined behaviour or performance.
Hard way to respect BTreeMap's minimum node length
Resolves#74834 the hard way (though not the hardest imaginable).
Benchmarks (which are all biased/realistic, inserting keys in ascending order) say:
```
benchcmp r0 r1 --threshold 10
name r0 ns/iter r1 ns/iter diff ns/iter diff % speedup
btree::map::clone_slim_100_and_clear 2,183 2,723 540 24.74% x 0.80
btree::map::clone_slim_100_and_drain_all 3,652 4,173 521 14.27% x 0.88
btree::map::clone_slim_100_and_drain_half 3,320 3,940 620 18.67% x 0.84
btree::map::clone_slim_100_and_into_iter 2,154 2,717 563 26.14% x 0.79
btree::map::clone_slim_100_and_pop_all 3,372 3,870 498 14.77% x 0.87
btree::map::clone_slim_100_and_remove_all 5,111 5,647 536 10.49% x 0.91
btree::map::clone_slim_100_and_remove_half 3,259 3,821 562 17.24% x 0.85
btree::map::iter_0 1,733 1,509 -224 -12.93% x 1.15
btree::map::iter_100 2,714 3,739 1,025 37.77% x 0.73
btree::map::iter_10k 3,728 4,269 541 14.51% x 0.87
btree::map::range_unbounded_unbounded 28,426 36,631 8,205 28.86% x 0.78
btree::map::range_unbounded_vs_iter 28,808 34,056 5,248 18.22% x 0.85
```
This difference is not caused by the `debug_assert`-related code in the function `splitpoint`, it's the same without.
The previous `assert_eq` generated quite some code, which is especially
problematic when this call is inlined. This commit also slightly
improves the panic message from:
assertion failed: `(left == right)`
left: `3`,
right: `2`: destination and source slices have different lengths
...to:
source slice length (2) does not match destination slice length (3)
fix wrong word in documentation
Change "two" to "three", since there are three significantly different things printed below that sentence:
---
While these:
```rust
println!("{}, `{name:.*}` has 3 fractional digits", "Hello", 3, name=1234.56);
println!("{}, `{name:.*}` has 3 characters", "Hello", 3, name="1234.56");
println!("{}, `{name:>8.*}` has 3 right-aligned characters", "Hello", 3, name="1234.56");
```
print two significantly different things:
``` rust
Hello, `1234.560` has 3 fractional digits
Hello, `123` has 3 characters
Hello, ` 123` has 3 right-aligned characters
```
---
[`https://doc.rust-lang.org/std/fmt/#precision`](https://doc.rust-lang.org/std/fmt/#precision)
Implement `into_keys` and `into_values` for associative maps
This PR implements `into_keys` and `into_values` for HashMap and BTreeMap types. They are implemented as unstable, under `map_into_keys_values` feature.
Fixes#55214.
r? @dtolnay