Do not allocate for ZST ThinBox (attempt 2 using const_allocate)
There's PR https://github.com/rust-lang/rust/pull/123184 which avoids allocation for ZST ThinBox.
That PR has an issue with unsoundness with padding in `MaybeUninit` (see comments in that PR). Also that PR relies on `Freeze` trait.
This PR is much simpler implementation which does not have this problem, but it uses `const_allocate` feature.
`@oli-obk` suggested that `const_allocate` should not be used for that feature. But I like how easy it to do this feature with `const_allocate`. Maybe it's OK to use `const_allocate` while `ThinBox` is unstable? Or, well, we can abandon this PR.
r? `@oli-obk`
There's PR https://github.com/rust-lang/rust/pull/123184
which avoids allocation for ZST ThinBox.
That PR has an issue with unsoundness with misuse of `MaybeUninit`
(see comments in that PR).
This PR is much simpler implementation which does not have this
problem, but it uses `const_allocate` feature.
Support running library tests in Miri
This adds a new bootstrap subcommand `./x.py miri` which can test libraries in Miri. This is in preparation for eventually doing that as part of bors CI, but this PR only adds the infrastructure, and doesn't enable it yet.
`@rust-lang/bootstrap` should this be `x.py test --miri library/core` or `x.py miri library/core`? The flag has the advantage that we don't have to copy all the arguments from `Subcommand::Test`. It has the disadvantage that most test steps just ignore `--miri` and still run tests the regular way. For clippy you went the route of making it a separate subcommand. ~~I went with a flag now as that seemed easier, but I can change this.~~ I made it a new subcommand. Note however that the regular cargo invocation would be `cargo miri test ...`, so `x.py` is still going to be different in that the `test` is omitted. That said, we could also make it `./x.py miri-test` to make that difference smaller -- that's in fact more consistent with the internal name of the command when bootstrap invokes cargo.
`@rust-lang/libs` ~~unfortunately this PR does some unholy things to the `lib.rs` files of our library crates.~~
`@m-ou-se` found a way that entirely avoids library-level hacks, except for some new small `lib.miri.rs` files that hopefully you will never have to touch. There's a new hack in cargo-miri but there it is in good company...
Remove len argument from RawVec::reserve_for_push
Removes `RawVec::reserve_for_push`'s `len` argument since it's always the same as capacity.
Also makes `Vec::insert` use `RawVec::reserve_for_push`.
Stabilize `unchecked_{add,sub,mul}`
Tracking issue: #85122
I think we might as well just stabilize these basic three. They're the ones that have `nuw`/`nsw` flags in LLVM.
Notably, this doesn't include the potentially-more-complex or -more-situational things like `unchecked_neg` or `unchecked_shr` that are under different feature flags.
To quote Ralf https://github.com/rust-lang/rust/issues/85122#issuecomment-1681669646,
> Are there any objections to stabilizing at least `unchecked_{add,sub,mul}`? For those there shouldn't be any surprises about what their safety requirements are.
*Semantially* these are [already available on stable, even in `const`, via](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=bdb1ff889b61950897f1e9f56d0c9a36) `checked_*`+`unreachable_unchecked`. So IMHO we might as well just let people write them directly, rather than try to go through a `let Some(x) = x.checked_add(y) else { unsafe { hint::unreachable_unchecked() }};` dance.
I added additional text to each method to attempt to better describe the behaviour and encourage `wrapping_*` instead.
r? rust-lang/libs-api
Eliminate `UbChecks` for non-standard libraries
The purpose of this PR is to allow other passes to treat `UbChecks` as constants in MIR for optimization after #122629.
r? RalfJung
Implement `Vec::pop_if`
This PR adds `Vec::pop_if` to the public API, behind the `vec_pop_if` feature.
```rust
impl<T> Vec<T> {
pub fn pop_if<F>(&mut self, f: F) -> Option<T>
where F: FnOnce(&mut T) -> bool;
}
```
Tracking issue: #122741
## Open questions
- [ ] Should the first unit test be split up?
- [ ] I don't see any guidance on ordering of methods in impl blocks, should I move the method elsewhere?
warning: casting raw pointers to the same type and constness is unnecessary (`*mut V` -> `*mut V`)
--> library\alloc\src\collections\btree\map\entry.rs:357:31
|
357 | let val_ptr = root.borrow_mut().push(self.key, value) as *mut V;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `root.borrow_mut().push
(self.key, value)`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast
warning: casting to the same type is unnecessary (`usize` -> `usize`)
--> library\alloc\src\ffi\c_str.rs:411:56
|
411 | let slice = slice::from_raw_parts_mut(ptr, len as usize);
| ^^^^^^^^^^^^ help: try: `len`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast
warning: casting raw pointers to the same type and constness is unnecessary (`*mut T` -> `*mut T`)
--> library\alloc\src\slice.rs:516:25
|
516 | (buf.as_mut_ptr() as *mut T).add(buf.len()),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `buf.as_mut_ptr()`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast
warning: casting raw pointers to the same type and constness is unnecessary (`*mut T` -> `*mut T`)
--> library\alloc\src\slice.rs:537:21
|
537 | (buf.as_mut_ptr() as *mut T).add(buf.len()),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `buf.as_mut_ptr()`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast
warning: casting raw pointers to the same type and constness is unnecessary (`*const ()` -> `*const ()`)
--> library\alloc\src\task.rs:151:13
|
151 | waker as *const (),
| ^^^^^^^^^^^^^^^^^^ help: try: `waker`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast
warning: casting raw pointers to the same type and constness is unnecessary (`*const ()` -> `*const ()`)
--> library\alloc\src\task.rs:323:13
|
323 | waker as *const (),
| ^^^^^^^^^^^^^^^^^^ help: try: `waker`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast
warning: casting to the same type is unnecessary (`usize` -> `usize`)
--> library\std\src\sys_common\net.rs:110:21
|
110 | assert!(len as usize >= mem::size_of::<c::sockaddr_in>());
| ^^^^^^^^^^^^ help: try: `len`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast
warning: casting to the same type is unnecessary (`usize` -> `usize`)
--> library\std\src\sys_common\net.rs:116:21
|
116 | assert!(len as usize >= mem::size_of::<c::sockaddr_in6>());
| ^^^^^^^^^^^^ help: try: `len`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast
Doc Guarantee: BTree(Set|Map): `IntoIter` Iterate in Sorted by key Order
This Doc-only PR adds text to the IntoIterator implementation and IntoIter type for both BTreeMap and BTreeSet that states that the returned items will be in sorted-by-key order, this is a guarantee that is made by the iter() and iter_mut() methods of BTreeMap/Set and BTreeMap respectively, but not on into_iter methods or types.
I don't know how the IntoIter iteration would not be sorted by key, and I would like to rely on that behavior for my prefix_array crate.
The text appended to IntoIter documentation is based on each types respective iter() method documentation, as is the text used in the IntoIterator documentation; they are slightly inconsistent between Set/Map, but they are consistent within their own types documentation.
select Vec::from_iter impls in a const block to optimize compile times
Ignoring whitespace diffs should make this easier to review.
This relies on the trick from #122301
Split out from #120682
Add `usize::MAX` arg tests for Vec
Tests to prevent recurrence of the UB from the rust-lang/rust#122760 issue.
I skipped the `with_capacity`, `drain`, `reserve`, etc. APIs because they actually had a good assortment of tests earlier in the same file.
r? Nilstrieb
Relax SeqCst ordering in standard library.
Every single SeqCst in the standard library is unnecessary. In all cases, Relaxed or Release+Acquire was sufficient.
As I [wrote](https://marabos.nl/atomics/memory-ordering.html#common-misconceptions) in my book on atomics:
> [..] when reading code, SeqCst basically tells the reader: "this operation depends on the total order of every single SeqCst operation in the program," which is an incredibly far-reaching claim. The same code would likely be easier to review and verify if it used weaker memory ordering instead, if possible. For example, Release effectively tells the reader: "this relates to an acquire operation on the same variable," which involves far fewer considerations when forming an understanding of the code.
>
> It is advisable to see SeqCst as a warning sign. Seeing it in the wild often means that either something complicated is going on, or simply that the author did not take the time to analyze their memory ordering related assumptions, both of which are reasons for extra scrutiny.
r? ````@Amanieu```` ````@joboet````
fix OOB pointer formed in Vec::index
Move the length check to before using `index` with `ptr::add` to prevent an out of bounds pointer from being formed.
Fixes#122760
Stabilize associated type bounds (RFC 2289)
This PR stabilizes associated type bounds, which were laid out in [RFC 2289]. This gives us a shorthand to express nested type bounds that would otherwise need to be expressed with nested `impl Trait` or broken into several `where` clauses.
### What are we stabilizing?
We're stabilizing the associated item bounds syntax, which allows us to put bounds in associated type position within other bounds, i.e. `T: Trait<Assoc: Bounds...>`. See [RFC 2289] for motivation.
In all position, the associated type bound syntax expands into a set of two (or more) bounds, and never anything else (see "How does this differ[...]" section for more info).
Associated type bounds are stabilized in four positions:
* **`where` clauses (and APIT)** - This is equivalent to breaking up the bound into two (or more) `where` clauses. For example, `where T: Trait<Assoc: Bound>` is equivalent to `where T: Trait, <T as Trait>::Assoc: Bound`.
* **Supertraits** - Similar to above, `trait CopyIterator: Iterator<Item: Copy> {}`. This is almost equivalent to breaking up the bound into two (or more) `where` clauses; however, the bound on the associated item is implied whenever the trait is used. See #112573/#112629.
* **Associated type item bounds** - This allows constraining the *nested* rigid projections that are associated with a trait's associated types. e.g. `trait Trait { type Assoc: Trait2<Assoc2: Copy>; }`.
* **opaque item bounds (RPIT, TAIT)** - This allows constraining associated types that are associated with the opaque without having to *name* the opaque. For example, `impl Iterator<Item: Copy>` defines an iterator whose item is `Copy` without having to actually name that item bound.
The latter three are not expressible in surface Rust (though for associated type item bounds, this will change in #120752, which I don't believe should block this PR), so this does represent a slight expansion of what can be expressed in trait bounds.
### How does this differ from the RFC?
Compared to the RFC, the current implementation *always* desugars associated type bounds to sets of `ty::Clause`s internally. Specifically, it does *not* introduce a position-dependent desugaring as laid out in [RFC 2289], and in particular:
* It does *not* desugar to anonymous associated items in associated type item bounds.
* It does *not* desugar to nested RPITs in RPIT bounds, nor nested TAITs in TAIT bounds.
This position-dependent desugaring laid out in the RFC existed simply to side-step limitations of the trait solver, which have mostly been fixed in #120584. The desugaring laid out in the RFC also added unnecessary complication to the design of the feature, and introduces its own limitations to, for example:
* Conditionally lowering to nested `impl Trait` in certain positions such as RPIT and TAIT means that we inherit the limitations of RPIT/TAIT, namely lack of support for higher-ranked opaque inference. See this code example: https://github.com/rust-lang/rust/pull/120752#issuecomment-1979412531.
* Introducing anonymous associated types makes traits no longer object safe, since anonymous associated types are not nameable, and all associated types must be named in `dyn` types.
This last point motivates why this PR is *not* stabilizing support for associated type bounds in `dyn` types, e.g, `dyn Assoc<Item: Bound>`. Why? Because `dyn` types need to have *concrete* types for all associated items, this would necessitate a distinct lowering for associated type bounds, which seems both complicated and unnecessary compared to just requiring the user to write `impl Trait` themselves. See #120719.
### Implementation history:
Limited to the significant behavioral changes and fixes and relevant PRs, ping me if I left something out--
* #57428
* #108063
* #110512
* #112629
* #120719
* #120584Closes#52662
[RFC 2289]: https://rust-lang.github.io/rfcs/2289-associated-type-bounds.html
Add slice::try_range
This adds a fallible version of the unstable `slice::range` (tracking: #76393) which is highly requested in the tracking issue.
Hoping this can slide by without an ACP (since the feature is already being tracked), but let me know otherwise.
Vec::try_with_capacity
Related to #91913
Implements try_with_capacity for `Vec`, `VecDeque`, and `String`. I can follow it up with more collections if desired.
`Vec::try_with_capacity()` is functionally equivalent to the current stable:
```rust
let mut v = Vec::new();
v.try_reserve_exact(n)?
```
However, `try_reserve` calls non-inlined `finish_grow`, which requires old and new `Layout`, and is designed to reallocate memory. There is benefit to using `try_with_capacity`, besides syntax convenience, because it generates much smaller code at the call site with a direct call to the allocator. There's codegen test included.
It's also a very desirable functionality for users of `no_global_oom_handling` (Rust-for-Linux), since it makes a very commonly used function available in that environment (`with_capacity` is used much more frequently than all `(try_)reserve(_exact)`).
Specifically, when an override doesn't just forward to an inner type,
document the behavior and that it's preferred over simply assigning
a clone of source. Also, change instances where the second parameter is
"other" to "source".
Add `#[inline]` to `BTreeMap::new` constructor
This PR add the `#[inline]` attribute to `BTreeMap::new` constructor as to make it eligible for inlining.
<details>
For some context: I was profiling `rustc --check-cfg` with callgrind and due to the way we currently setup all the targets and we end-up calling `BTreeMap::new` multiple times for (nearly) all the targets. Adding the `#[inline]` attribute reduced the number of instructions needed.
</details>
only set noalias on Box with the global allocator
As discovered in https://github.com/rust-lang/miri/issues/3341, `noalias` and custom allocators don't go well together.
rustc can now check whether a Box uses the global allocator. This replaces the previous ad-hoc and rather unprincipled check for a zero-sized allocator.
This is the rustc part of fixing that; Miri will also need a patch.
const_eval_select: make it safe but be careful with what we expose on stable for now
As this is all still nightly-only I think `````@rust-lang/wg-const-eval````` can do that without involving t-lang.
r? `````@oli-obk`````
Cc `````@Nilstrieb````` -- the updated version of your RFC would basically say that we can remove these comments about not making behavior differences visible in stable `const fn`
Clarify/add `must_use` message for Rc/Arc/Weak::into_raw.
The current `#[must_use]` messages for `{sync,rc}::Weak::into_raw` ("`self` will be dropped if the result is not used") are misleading, as `self` is consumed and will *not* be dropped.
This PR changes their `#[must_use]` message to the same as `Arc::into_raw`'s[ current `#[must_use]` message](d573564575/library/alloc/src/sync.rs (L1482)) ("losing the pointer will leak memory"), and also adds it to `Rc::into_raw`, which is not currently `#[must_use]`.
Preserve same vtable pointer when cloning raw waker, to fix Waker::will_wake
Fixes#121600.
As `@jkarneges` identified in https://github.com/rust-lang/rust/issues/121600#issuecomment-1963041051, the issue is two different const promotions produce two statics at different addresses, which may or may not later be deduplicated by the linker (in this case not).
Prior to #119863, the content of the statics was compared, and they were equal. After, the address of the statics are compared and they are not equal.
It is documented that `will_wake` _"works on a best-effort basis, and may return false even when the Wakers would awaken the same task"_ so this PR fixes a quality-of-implementation issue, not a correctness issue.
Have `String` use `SliceIndex` impls from `str`
This PR simplifies the implementation of `Index` and `IndexMut` on `String`, and in the process enables indexing `String` by any user types that implement `SliceIndex<str>`.
Similar to #47832
r? libs
Not sure if this warrants a crater run.
Those libraries are build with `-C panic=unwind` and is expected to
be linkable to `-C panic=abort` library. To ensure unsoundness
compiler needs to prevent a `C-unwind` call to exist, as doing so may leak
foreign exceptions into `-C panic=abort`.
Help with common API confusion, like asking for `push` when the data structure really has `append`.
```
error[E0599]: no method named `size` found for struct `Vec<{integer}>` in the current scope
--> $DIR/rustc_confusables_std_cases.rs:17:7
|
LL | x.size();
| ^^^^
|
help: you might have meant to use `len`
|
LL | x.len();
| ~~~
help: there is a method with a similar name
|
LL | x.resize();
| ~~~~~~
```
#59450
Remove useless `'static` bounds on `Box` allocator
#79327 added `'static` bounds to the allocator parameter for various `Box` + `Pin` APIs to ensure soundness. But it was a bit overzealous, some of the bounds aren't actually needed.
Remove unnecessary unit binding
It appears that the unit binding is not necessary at this time. However, I am unsure of its importance in the past. Please let me know if it is unsafe to remove.
Fix typo in VecDeque::handle_capacity_increase() doc comment.
Strategies B and C both show a full buffer before the capacity increase, while strategy A had one empty element left. Filled the last element in.
Fix BTreeMap's Cursor::remove_{next,prev}
These would incorrectly leave `current` as `None` after a failed attempt to remove an element (due to the cursor already being at the start/end).
Additional doc links and explanation of `Wake`.
This is intended to clarify:
* That `Wake` exists and can be used instead of `RawWaker`.
* How to construct a `Waker` when you are looking at `Wake` (which was previously only documented in the example).
docs: mention round-to-even in precision formatting
_Note_: Not quite sure exactly how to format this documentation.
Mentions round-to-even usage in precision formatting. (should this also be mentioned in `f64::round`?)
From https://github.com/rust-lang/rust/issues/70336
improve `btree_cursors` functions documentation
As suggested by ``@Amanieu`` (and others) in #107540 (https://github.com/rust-lang/rust/issues/107540#issuecomment-1937760547)
Improvements:
- Document exact behavior of `{upper/lower}_bound{,_mut}` with each of the three `Bound` types using unambigous words `{greatest,greater,smallest,smaller,before,after}`.
- Added another doc-example for the `Bound::Unbounded` for each of the methods
- Changed doc-example to use From<[T; N]> rather than lots of `insert()`s which requires a mutable map which clutters the example when `mut` may not be required for the method (such as for `{upper,lower}_bound`.
- Removed `# Panics` section from `insert_{before,after}` methods since they were changed to return an error instead a while ago.
- Reworded some phrases to be more consistent with the more regular `BTreeMap` methods such as calling entries "key-value" rather than "element"s.
Create try_new function for ThinBox
The `allocator_api` feature has proven very useful in my work in the FreeBSD kernel. I've found a few places where a `ThinBox` #92791 would be useful, but it must be able to be fallibly allocated for it to be used in the kernel.
This PR proposes a change to add such a constructor for ThinBox.
ACP: https://github.com/rust-lang/libs-team/issues/213
Add some links and minor explanatory comments to `std::fmt`
I thought the documentation for the `#` flag could do with a link to the explanation of the `?xXbo` flags, because at that point they haven't been explained yet and it's a bit confusing.
I also added that the `0` flag overrides the fill character and alignment flag, here's a [Rust Playgrond](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=0d580b7b78b8a2d8c08a2fc7a936ef17) that shows what I mean.
This is intended to clarify:
* That `Wake` exists and can be used instead of `RawWaker`.
* How to construct a `Waker` when you are looking at `Wake`
(which was previously only documented in the example).
Harmonize `AsyncFn` implementations, make async closures conditionally impl `Fn*` traits
This PR implements several changes to the built-in and libcore-provided implementations of `Fn*` and `AsyncFn*` to address two problems:
1. async closures do not implement the `Fn*` family traits, leading to breakage: https://crater-reports.s3.amazonaws.com/pr-120361/index.html
2. *references* to async closures do not implement `AsyncFn*`, as a consequence of the existing blanket impls of the shape `AsyncFn for F where F: Fn, F::Output: Future`.
In order to fix (1.), we implement `Fn` traits appropriately for async closures. It turns out that async closures can:
* always implement `FnOnce`, meaning that they're drop-in compatible with `FnOnce`-bound combinators like `Option::map`.
* conditionally implement `Fn`/`FnMut` if they have no captures, which means that existing usages of async closures should *probably* work without breakage (crater checking this: https://github.com/rust-lang/rust/pull/120712#issuecomment-1930587805).
In order to fix (2.), we make all of the built-in callables implement `AsyncFn*` via built-in impls, and instead adjust the blanket impls for `AsyncFn*` provided by libcore to match the blanket impls for `Fn*`.
`std::error::Error` -> Trait Implementations: lifetimes consistency improvement
This cleans up `std::error::Error` trait implementations lifetime inconsistency (`'static` -> `'a`)
**Reasoning:**
Trait implementations for `std::error::Error`, like:
`impl From<&str> for Box<dyn Error + 'static, Global>`
`impl<'a> From<&str> for Box<dyn Error + Sync + Send + 'a, Global>`
use different lifetime annotations misleadingly implying using different life annotations here is a conscious, nonaccidental decision.
[(Related forum discussion here)](https://users.rust-lang.org/t/confusing-std-error-source-code/97011/5?u=wiktor)
document `FromIterator for Vec` allocation behaviors
[t-libs discussion](https://rust-lang.zulipchat.com/#narrow/stream/259402-t-libs.2Fmeetings/topic/Meeting.202024-01-24/near/417686526) about #120091 didn't reach a strong consensus, but it was agreed that if we keep the current behavior it should at least be documented even though it is an implementation detail.
The language is intentionally non-committal. The previous (non-existent) documentation permits a lot of implementation leeway and we want retain that. In some cases we even must retain it to be able to rip out some code paths that rely on unstable features.
Fix some `Arc` allocator leaks
This doesn't matter for the stable `Global` allocator as it is a ZST singleton, but other allocators may rely on all instances being dropped.
impl `From<&[T; N]>` for `Cow<[T]>`
Implement `From<&[T; N]>` for `Cow<[T]>` to simplify its usage in the following example.
```rust
fn foo(data: impl Into<Cow<'static, [&'static str]>>) { /* ... */ }
fn main() {
foo(vec!["hello", "world"]);
foo(&["hello", "world"]); // Error: the trait `From<&[&str; 2]>` is not implemented for `Cow<'static, [&'static str]>`
foo(&["hello", "world"] as &[_]); // Explicit convertion into a slice is required
}
```
stabilise array methods
Closes#76118
Stabilises the remaining array methods
FCP is yet to be carried out for this
There wasn't a clear consensus on the naming, but all the other alternatives had some flaws as discussed in the tracking issue and there was a silence on this issue for a year
Remove special-case handling of `vec.split_off(0)`
#76682 added special handling to `Vec::split_off` for the case where `at == 0`. Instead of copying the vector's contents into a freshly-allocated vector and returning it, the special-case code steals the old vector's allocation, and replaces it with a new (empty) buffer with the same capacity.
That eliminates the need to copy the existing elements, but comes at a surprising cost, as seen in #119913. The returned vector's capacity is no longer determined by the size of its contents (as would be expected for a freshly-allocated vector), and instead uses the full capacity of the old vector.
In cases where the capacity is large but the size is small, that results in a much larger capacity than would be expected from reading the documentation of `split_off`. This is especially bad when `split_off` is called in a loop (to recycle a buffer), and the returned vectors have a wide variety of lengths.
I believe it's better to remove the special-case code, and treat `at == 0` just like any other value:
- The current documentation states that `split_off` returns a “newly allocated vector”, which is not actually true in the current implementation when `at == 0`.
- If the value of `at` could be non-zero at runtime, then the caller has already agreed to the cost of a full memcpy of the taken elements in the general case. Avoiding that copy would be nice if it were close to free, but the different handling of capacity means that it is not.
- If the caller specifically wants to avoid copying in the case where `at == 0`, they can easily implement that behaviour themselves using `mem::replace`.
Fixes#119913.
Initial implementation of `str::from_raw_parts[_mut]`
ACP (accepted): rust-lang/libs-team#167
Tracking issue: #119206
Thanks to ``@Kixiron`` for previous work on this (#107207)
``@rustbot`` label +T-libs-api -T-libs
r? ``@thomcc``
Closes#107207.
Use `assert_unchecked` instead of `assume` intrinsic in the standard library
Now that a public wrapper for the `assume` intrinsic exists, we can use it in the standard library.
CC #119131
Fix deallocation with wrong allocator in (A)Rc::from_box_in
Deallocate the `Box` with the original allocator (via `&A`), not `Global`.
Fixes#119749
<details> <summary>Example code with error and Miri output</summary>
(Note that this UB is not observable on stable, because the only usable allocator on stable is `Global` anyway.)
Code ([playground link](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=96193c2c6a1912d7f669fbbe39174b09)):
```rs
#![feature(allocator_api)]
use std::alloc::System;
// uncomment one of these
use std::rc::Rc;
//use std::sync::Arc as Rc;
fn main() {
let x: Box<[u32], System> = Box::new_in([1,2,3], System);
let _: Rc<[u32], System> = Rc::from(x);
}
```
Miri output:
```rs
error: Undefined Behavior: deallocating alloc904, which is C heap memory, using Rust heap deallocation operation
--> /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/alloc.rs:117:14
|
117 | unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ deallocating alloc904, which is C heap memory, using Rust heap deallocation operation
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `std::alloc::dealloc` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/alloc.rs:117:14: 117:64
= note: inside `<std::alloc::Global as std::alloc::Allocator>::deallocate` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/alloc.rs:254:22: 254:51
= note: inside `<std::boxed::Box<std::mem::ManuallyDrop<[u32]>> as std::ops::Drop>::drop` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/boxed.rs:1244:17: 1244:66
= note: inside `std::ptr::drop_in_place::<std::boxed::Box<std::mem::ManuallyDrop<[u32]>>> - shim(Some(std::boxed::Box<std::mem::ManuallyDrop<[u32]>>))` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:507:1: 507:56
= note: inside `std::mem::drop::<std::boxed::Box<std::mem::ManuallyDrop<[u32]>>>` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/mem/mod.rs:992:24: 992:25
= note: inside `std::rc::Rc::<[u32], std::alloc::System>::from_box_in` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/rc.rs:1928:13: 1928:22
= note: inside `<std::rc::Rc<[u32], std::alloc::System> as std::convert::From<std::boxed::Box<[u32], std::alloc::System>>>::from` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/rc.rs:2504:9: 2504:27
note: inside `main`
--> src/main.rs:10:32
|
10 | let _: Rc<[u32], System> = Rc::from(x);
| ^^^^^^^^^^^
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error
```
</details>
Document some alternatives to `Vec::split_off`
One of the discussion points that came up in #119917 is that some people use `Vec::split_off` in cases where they probably shouldn't, because the alternatives (like `mem::take`) are hard to discover.
This PR adds some suggestions to the documentation of `split_off` that should point people towards alternatives that might be more appropriate for their use-case.
I've deliberately tried to keep these changes as simple and uncontroversial as possible, so that they don't depend on how the team decides to handle the concerns raised in #119917. That's why I haven't touched the existing documentation for `split_off`, and haven't added links to `split_off` to the documentation of other methods.
fix: Drop guard was deallocating with the incorrect size
InPlaceDstBufDrop holds onto the allocation before the shrinking happens which means it must deallocate the destination elements but the source allocation.
Thanks `@cuviper` for spotting this.
Implement iterator specialization traits on more adapters
This adds
* `TrustedLen` to `Skip` and `StepBy`
* `TrustedRandomAccess` to `Skip`
* `InPlaceIterable` and `SourceIter` to `Copied` and `Cloned`
The first two might improve performance in the compiler itself since `skip` is used in several places. Constellations that would exercise the last point are probably rare since it would require an owning iterator that has references as Items somewhere in its iterator pipeline.
Improvements for `Skip`:
```
# old
test iter::bench_skip_trusted_random_access ... bench: 8,335 ns/iter (+/- 90)
# new
test iter::bench_skip_trusted_random_access ... bench: 2,753 ns/iter (+/- 27)
```
Remove alignment-changing in-place collect
This removes the alignment-changing in-place collect optimization introduced in #110353
Currently stable users can't benefit from the optimization because GlobaAlloc doesn't support alignment-changing realloc and neither do most posix allocators. So in practice it has a negative impact on performance.
Explanation from https://github.com/rust-lang/rust/issues/120091#issuecomment-1899071681:
> > You mention that in case of alignment mismatch -- when the new alignment is less than the old -- the implementation calls `mremap`.
>
> I was trying to note that this isn't really the case in practice, due to the semantics of Rust's allocator APIs. The only use of the allocator within the `in_place_collect` implementation itself is [a call to `Allocator::shrink()`](db7125f008/library/alloc/src/vec/in_place_collect.rs (L299-L303)), which per its documentation [allows decreasing the required alignment](https://doc.rust-lang.org/1.75.0/core/alloc/trait.Allocator.html). However, in stable Rust, the only available `Allocator` is [`Global`](https://doc.rust-lang.org/1.75.0/alloc/alloc/struct.Global.html), which delegates to the registered `GlobalAlloc`. Since `GlobalAlloc::realloc()` [cannot change the required alignment](https://doc.rust-lang.org/1.75.0/core/alloc/trait.GlobalAlloc.html#method.realloc), the implementation of [`<Global as Allocator>::shrink()`](db7125f008/library/alloc/src/alloc.rs (L280-L321)) must fall back to creating a brand-new allocation, `memcpy`ing the data into it, and freeing the old allocation, whenever the alignment doesn't remain exactly the same.
>
> Therefore, the underlying allocator, provided by libc or some other source, has no opportunity to internally `mremap()` the data when the alignment is changed, since it has no way of knowing that the allocation is the same.
This also removes
* impl From<&Context> for ContextBuilder
* Context::try_waker()
The from implementation is removed because now that
wakers are always supported, there are less incentives
to override the current context. Before, the incentive
was to add Waker support to a reactor that didn't have
any.
InPlaceDstBufDrop holds onto the allocation before the shrinking happens
which means it must deallocate the destination elements but the source
allocation.
Update documentation for Vec::into_boxed_slice to be more clear about excess capacity
Currently, the documentation for Vec::into_boxed_slice says that "if the vector has excess capacity, its items will be moved into a newly-allocated buffer with exactly the right capacity." This is misleading, as copies do not necessarily occur, depending on if the allocator supports in-place shrinking. I copied some of the wording from shrink_to_fit, though it could potentially still be worded better than this.
Currently stable users can't benefit from this because GlobaAlloc doesn't support
alignment-changing realloc and neither do most posix allocators.
So in practice it always results in an extra memcpy.