Commit Graph

2641 Commits

Author SHA1 Message Date
Matthias Krüger fa99ebc7cf
Rollup merge of #122817 - ultrabear:ultrabear_btreedoc, r=Nilstrieb
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.
2024-03-22 01:07:30 +01:00
bors 0ad927c0c0 Auto merge of #122785 - the8472:const-select-specialized-impl, r=Amanieu
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
2024-03-21 21:19:19 +00:00
ultrabear beb0c22c09
document into_iter in top level docs iterator ordering guarantees 2024-03-21 02:07:46 -07:00
ultrabear f8a093c8ea
document iteration ordering on into_iter method instead of IntoIterator implementation 2024-03-21 02:05:11 -07:00
ultrabear f6f89dc202
BTree(Set|Map): Guarantee that `IntoIter` will iterate in sorted by key order 2024-03-21 00:54:50 -07:00
Jacob Pratt 7a5ffccded
Rollup merge of #122765 - workingjubilee:test-for-vec-handling-usize-max, r=Nilstrieb
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
2024-03-20 20:29:46 -04:00
Jacob Pratt 43ad753adb
Rollup merge of #122729 - m-ou-se:relax, r=Amanieu
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````
2024-03-20 20:29:44 -04:00
bors 1388d7a069 Auto merge of #122761 - jwong101:fix/vec-insert, r=workingjubilee,Nilstrieb
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
2024-03-20 21:37:30 +00:00
The 8472 3ff1e448e7 select Vec::from_iter impls in a const block to optimize compile times 2024-03-20 19:26:38 +01:00
bors a128516cf9 Auto merge of #122754 - Mark-Simulacrum:bootstrap-bump, r=albertlarsan68
Bump to 1.78 bootstrap compiler

https://forge.rust-lang.org/release/process.html#master-bootstrap-update-t-2-day-tuesday
2024-03-20 13:43:41 +00:00
Mark Rousskov 02f1930595 step cfgs 2024-03-20 08:49:13 -04:00
Jubilee Young 92f668c20b Add usize::MAX arg tests for Vec 2024-03-20 01:21:19 -07:00
Joshua Wong 37718f949f 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
2024-03-19 22:47:35 -05:00
Michael Goulet 05116c5c30 Only split by-ref/by-move futures for async closures 2024-03-19 16:59:23 -04:00
Mara Bos a2c74b8445 SeqCst->Relaxed in doc examples.
SeqCst is unnecessary here.
2024-03-19 15:27:11 +01:00
bors 21d94a3d2c Auto merge of #122055 - compiler-errors:stabilize-atb, r=oli-obk
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
* #120584

Closes #52662

[RFC 2289]: https://rust-lang.github.io/rfcs/2289-associated-type-bounds.html
2024-03-19 00:04:09 +00:00
Matthias Krüger 223c23c63f
Rollup merge of #122642 - pallix:improve-wording-for-vec-swap_remove, r=Amanieu
Improve wording of `Vec::swap_remove`

This improve the wording for  `Vec::swap_remove`.
2024-03-18 22:24:38 +01:00
Reed 7b3ef13146 Fix a typo in the alloc::string::String docs 2024-03-18 11:39:00 -07:00
Ralf Jung c96fa5e143 add_retag: ensure box-to-raw-ptr casts are preserved for Miri 2024-03-18 10:32:25 +01:00
Pierre Allix 23e1b570d7 Improve wording of `Vec::swap_remove` 2024-03-17 18:27:02 +01:00
Scott McMurray 234e383c34 Stabilize `unchecked_{add,sub,mul}` 2024-03-14 18:39:37 -07:00
Arthur Carcano ccd99b384e Remove unused fields in some structures
The dead_code lint was previously eroneously missing those.
Since this lint bug has been fixed, the unused fields need
to be removed.
2024-03-12 10:59:40 +01:00
Jacob Pratt eb1ebbfc92
Rollup merge of #122298 - RalfJung:raw-vec-into-box, r=cuviper
RawVec::into_box: avoid unnecessary intermediate reference

Fixes the problem described [here](https://github.com/rust-lang/miri/issues/3341#issuecomment-1987207195).
2024-03-11 03:47:21 -04:00
Jacob Pratt 6c8c272ad4
Rollup merge of #121148 - clarfonthey:try-range, r=dtolnay
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.
2024-03-11 03:47:18 -04:00
Ralf Jung 81ebaf27cb RawVec::into_box: avoid unnecessary intermediate reference 2024-03-10 18:07:34 +01:00
Matthias Krüger 1b44889ec2
Rollup merge of #112136 - clarfonthey:ffi-c_str, r=cuviper
Add std::ffi::c_str module

ACP: rust-lang/libs-team#134

`std::ffi` docs before change:
![Structs: VaList, VaListImpl, CStr, CString, FromBytesWithNulError, FromVecWithNulError, IntoStringError, NulError, OsStr, OsString](https://github.com/rust-lang/rust/assets/15850505/b2cf3534-30f9-4ef0-a655-bacdc3a19e17)

`std::ffi` docs after change:
![Re-exports: self::c_str::{FromBytesWithNulError, FromBytesUntilNulError, FromVecWithNulError, NulError, IntoStringError} ; Modules: c_str ; Structs: VaList, VaListImpl, CStr, CString, OsStr, OsString](https://github.com/rust-lang/rust/assets/15850505/23aa6964-da7a-4942-bbf7-42bde2146f9e)

(note: I'm omitting the `c_int`, etc. stuff from the screenshots since it's the same in both. this doesn't just delete those types)
2024-03-10 10:58:14 +01:00
Guillaume Boisseau e3c0158788
Rollup merge of #120504 - kornelski:try_with_capacity, r=Amanieu
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)`).
2024-03-09 21:40:06 +01:00
Ralf Jung e632e3f9a5 miri: do not apply aliasing restrictions to Box with custom allocator 2024-03-09 13:08:55 +01:00
Michael Goulet c63f3feb0f Stabilize associated type bounds 2024-03-08 20:56:25 +00:00
Noa c0e913fdd7
Document overrides of `clone_from()`
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".
2024-03-08 12:27:24 -06:00
Matthias Krüger d16c55d6f6
Rollup merge of #122099 - Urgau:btreemap-inline-new, r=Amanieu
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>
2024-03-08 08:19:19 +01:00
Ralf Jung 1a2bc1102d Rust is a proper name: rust → Rust 2024-03-07 07:49:22 +01:00
Urgau cc38c1e9cb Add #[inline] to BTreeMap::new constructor 2024-03-06 19:14:03 +01:00
Matthias Krüger b08837f180
Rollup merge of #122018 - RalfJung:box-custom-alloc, r=oli-obk
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.
2024-03-05 22:10:02 +01:00
Matthias Krüger 076043346d
Rollup merge of #122016 - RalfJung:will_wake, r=dtolnay
will_wake tests fail on Miri and that is expected

Follow-up to https://github.com/rust-lang/rust/pull/121622
r? ```@cuviper``` ```@dtolnay```
2024-03-05 22:10:02 +01:00
Matthias Krüger 327842b4ab
Rollup merge of #121894 - RalfJung:const_eval_select, r=oli-obk
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`
2024-03-05 22:10:01 +01:00
Ralf Jung f391c0793b only set noalias on Box with the global allocator 2024-03-05 15:03:33 +01:00
Ralf Jung 960dd38abe will_wake tests fail on Miri and that is expected 2024-03-05 09:33:55 +01:00
Matthias Krüger 72651306b3
Rollup merge of #121287 - zachs18:rc-into-raw-must-use, r=cuviper
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]`.
2024-03-05 06:40:30 +01:00
Matthias Krüger 22827fd5b1
Rollup merge of #121262 - 20jasper:add-vector-time-complexity, r=cuviper
Add vector time complexity

Added time complexity for `Vec` methods `push`, `push_within_capacity`, `pop`, and `insert`.

<details>

<summary> Reference images </summary>

![`Vec::push` documentation](https://github.com/rust-lang/rust/assets/78604367/dc966bbd-e92e-45a6-af82-35afabfa79a9)

![`Vec::push_within_capacity` documentation](https://github.com/rust-lang/rust/assets/78604367/9aadaf48-46ed-4fad-bdd5-74b98a61f4bb)

![`Vec::pop` documentation](https://github.com/rust-lang/rust/assets/78604367/88ec0389-a346-4ea5-a3b7-17caf514dd8b)

![`Vec::insert` documentation](https://github.com/rust-lang/rust/assets/78604367/960c15c3-ef8e-4aa7-badc-35ce80f6f221)

</details>

I followed a convention to use `#Time complexity` that I found in [the `BinaryHeap` documentation](https://doc.rust-lang.org/std/collections/struct.BinaryHeap.html#time-complexity-1). Looking through the rest of standard library collections, there is not a consistent way to handle this.

[`Vec::swap_remove`](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.swap_remove) does not have a dedicated section for time complexity but does list it.

[`VecDeque::rotate_left`](https://doc.rust-lang.org/std/collections/struct.VecDeque.html#complexity) uses a `#complexity` heading.
2024-03-05 06:40:29 +01:00
Matthias Krüger c2f6c0b806
Rollup merge of #121213 - Takashiidobe:takashi/example-for-rc-into-inner, r=cuviper
Add an example to demonstrate how Rc::into_inner works

This PR adds an example to Rc::into_inner, since it didn't have one previously.
2024-03-05 06:40:29 +01:00
Guillaume Boisseau b0ca9b5d44
Rollup merge of #121622 - dtolnay:wake, r=cuviper
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.
2024-03-02 20:13:22 +01:00
Ralf Jung 374607d6b9 const_eval_select: make it safe but be careful with what we expose on stable for now 2024-03-02 16:09:31 +01:00
Kornel 784e6a1e08 Move capacity_overflow function to make ui tests change less
Code changes in raw_vec require blessing UI tests every time
2024-03-01 18:24:02 +00:00
Kornel 78fb977d6b try_with_capacity for Vec, VecDeque, String
#91913
2024-03-01 18:24:02 +00:00
Kornel f27a22c24a try_with_capacity for RawVec 2024-03-01 18:20:48 +00:00
Alexander fb8ac06477 remove hidden use of Global 2024-03-01 11:51:28 +00:00
Jacob Pratt 6d865038a5
Rollup merge of #120291 - pitaj:string-sliceindex, r=Amanieu
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.
2024-02-29 05:25:26 -05:00
Peter Jaszkowiak 5d59d0c7d7 have `String` use `SliceIndex` impls from `str` 2024-02-27 09:41:32 -07:00
David Tolnay db535bad79
Generate original vtable and clone's vtable in the same CGU 2024-02-26 20:56:44 -08:00
许杰友 Jieyou Xu (Joe) bfeea294cc
Document args returned from `String::into_raw_parts` 2024-02-26 19:32:32 +00:00
许杰友 Jieyou Xu (Joe) dd24a462d5
Document args returned from `Vec::into_raw_parts{,_with_alloc}` 2024-02-26 19:32:32 +00:00
许杰友 Jieyou Xu (Joe) 26bdf2900a
Rearrange `String::from_raw_parts` doc argument order to match code argument order 2024-02-26 19:32:26 +00:00
许杰友 Jieyou Xu (Joe) a1b93e8fed
Rearrange `Vec::from_raw_parts{,_in}` doc argument order to match code argument order 2024-02-26 19:32:17 +00:00
David Tolnay 793b45f53a
Add Waker::will_wake tests
Currently fails:

    ---- task::test_waker_will_wake_clone stdout ----
    thread 'task::test_waker_will_wake_clone' panicked at library/alloc/tests/task.rs:17:5:
    assertion failed: waker.will_wake(&clone)
2024-02-25 20:55:12 -08:00
Jacob Asper 74151cbbf0 Make push docs more vague 2024-02-25 02:43:21 -05:00
Matthias Krüger 4c401531f5
Rollup merge of #121556 - GrigorenkoPV:addr_of, r=Nilstrieb
Use `addr_of!`

As per https://github.com/rust-lang/rust/pull/121303#discussion_r1500954662
2024-02-24 22:39:01 +01:00
Gary Guo f08e2d4137 Forbid use of `extern "C-unwind"` inside standard library
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`.
2024-02-24 14:53:04 +00:00
Pavel Grigorenko ff187a92d8
library: use `addr_of!` 2024-02-24 16:02:17 +03:00
bors 21033f637e Auto merge of #121514 - matthiaskrgr:rollup-5f0vhv7, r=matthiaskrgr
Rollup of 6 pull requests

Successful merges:

 - #120742 (mark `min_exhaustive_patterns` as complete)
 - #121470 (Don't ICE on anonymous struct in enum variant)
 - #121492 (coverage: Rename `is_closure` to `is_hole`)
 - #121495 (remove repetitive words)
 - #121498 (Make QNX/NTO specific "timespec capping" public to crate::sys)
 - #121510 (lint-overflowing-ops: unify cases and remove redundancy)

r? `@ghost`
`@rustbot` modify labels: rollup
2024-02-23 16:26:49 +00:00
bors b6a23b8537 Auto merge of #121454 - reitermarkus:generic-nonzero-library, r=dtolnay
Use generic `NonZero` everywhere in `library`.

Tracking issue: https://github.com/rust-lang/rust/issues/120257

Use generic `NonZero` everywhere (except stable examples).

r? `@dtolnay`
2024-02-23 14:27:33 +00:00
cui fliter 824d75c22e remove repetitive words
Signed-off-by: cui fliter <imcusg@gmail.com>
2024-02-23 18:26:01 +08:00
Esteban Küber 0e89465672 On type error of method call arguments, look at confusables for suggestion 2024-02-22 18:04:55 +00:00
Esteban Küber e5b3c7ef14 Add `rustc_confusables` annotations to some stdlib APIs
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
2024-02-22 18:04:55 +00:00
Markus Reiter 36d194f561
Use generic `NonZero` everywhere in `alloc`. 2024-02-22 15:17:34 +01:00
ltdk 1ea6cd715e Add std::ffi::c_str modules 2024-02-22 02:09:26 -05:00
bors c5f69bdd51 Auto merge of #118634 - Jules-Bertholet:box-allocator-static, r=Amanieu
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.
2024-02-22 02:03:29 +00:00
Ralf Jung b58f647d54 rename ptr::invalid -> ptr::without_provenance
also introduce ptr::dangling matching NonNull::dangling
2024-02-21 20:15:52 +01:00
Zachary S 261da5fc4b Clarify/add `must_use` message for Rc/Arc/Weak::into_raw. 2024-02-18 22:43:42 -06:00
Jacob Asper bc52e5d4de Fix error in push docs
Copying is O(n)—not the memory allocation
2024-02-18 17:55:52 -05:00
Matthias Krüger c8f2a00aec
Rollup merge of #121224 - hi-rustin:rustin-patch-unit-binding, r=Mark-Simulacrum
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.
2024-02-18 18:54:33 +01:00
Jacob Asper a9cfeb34dd fix typo in push documentation 2024-02-18 06:02:05 -05:00
Jacob Asper ef1a584842 intradoc link for vec 2024-02-18 05:47:30 -05:00
Jacob Asper d2f825f261 time complexity for insert 2024-02-18 05:21:33 -05:00
Jacob Asper 0a5d6841e8 time complexity for pop 2024-02-18 05:21:33 -05:00
Jacob Asper bb6dca0fc8 time complexity for push_within_capacity 2024-02-18 05:21:33 -05:00
Jacob Asper cb8ce9d9e5 time complexity for push 2024-02-18 05:21:33 -05:00
bors 158f00a1c5 Auto merge of #118264 - lukas-code:optimized-draining, r=the8472
Optimize `VecDeque::drain` for (half-)open ranges

The most common use cases of `VecDeque::drain` consume either the entire queue or elements from the front or back.[^1] This PR makes these operations faster by optimizing the generated code of the destructor of the drain:

* `.drain(..)` is now the same as `.clear()`.
* `.drain(n..)` is now (almost[^2]) the same as `.truncate(n)`.
* `.drain(..n)` is now an efficient "advance" function. This operation is not provided by a dedicated function and optimizing it is my main motivation for this PR.

Previously, all of these cases generated a function call to the destructor of the `DropGuard`, emitting a lot of unused machine code as well as unnecessary branches and loads/stores of stack variables.

There are no algorithmic changes in this PR, but it simplifies the code enough to allow LLVM to recognize the special cases and optimize accordingly. Most notably, it allows elimination of the rather large [`wrap_copy`] function.

Some [rudimentary microbenchmarks][benches] show a performance improvement of **~3x-4x** on my machine for the special cases and roughly equal performance for the general case.

Best reviewed commit by commit.

[^1]: source: GitHub code search: [full range `drain(..)` = 7.5k results][full], [from front `drain(..n)` = 3.2k results][front], [from back `drain(n..)` = 1.6k results][back], [from middle `drain(n..m)` = <500 results][middle]

[^2]: `.drain(0..)` and `.clear()` reset the head to 0, but `.truncate(0)` does not.

[full]: https://github.com/search?type=code&q=%2FVecDeque%28.%7C%5Cn%29%2B%5C.drain%5C%280%3F%5C.%5C.%5C%29%2F+lang%3ARust
[front]: https://github.com/search?type=code&q=%2FVecDeque%28.%7C%5Cn%29%2B%5C.drain%5C%280%3F%5C.%5C.%5B%5E%29%5D.*%5C%29%2F+lang%3ARust
[back]: https://github.com/search?type=code&q=%2FVecDeque%28.%7C%5Cn%29%2B%5C.drain%5C%28%5B%5E0%5D.*%5C.%5C.%5C%29%2F+lang%3ARust
[middle]: https://github.com/search?type=code&q=%2FVecDeque%28.%7C%5Cn%29%2B%5C.drain%5C%28%5B%5E0%5D.*%5C.%5C.%5B%5E%29%5D.*%5C%29%2F+lang%3ARust
[`wrap_copy`]: 4fd68eb47b/library/alloc/src/collections/vec_deque/mod.rs (L262-L391)
[benches]: https://gist.github.com/lukas-code/c97bd707d074c4cc31f241edbc7fd2a2

<details>
<summary>generated assembly</summary>

before:
```asm
clear:
	sub rsp, 40
	mov rax, qword ptr [rdi + 24]
	mov qword ptr [rdi + 24], 0
	mov qword ptr [rsp], rdi
	mov qword ptr [rsp + 8], rax
	xorps xmm0, xmm0
	movups xmmword ptr [rsp + 16], xmm0
	mov qword ptr [rsp + 32], rax
	test rax, rax
	je .LBB1_2
	mov rcx, qword ptr [rdi]
	mov rdx, qword ptr [rdi + 16]
	xor esi, esi
	cmp rdx, rcx
	cmovae rsi, rcx
	sub rdx, rsi
	mov rsi, rcx
	sub rsi, rdx
	lea rdi, [rdx + rax]
	cmp rsi, rax
	cmovb rdi, rcx
	sub rdi, rdx
	mov qword ptr [rsp + 16], rdi
	mov qword ptr [rsp + 32], 0
.LBB1_2:
	mov rdi, rsp
	call core::ptr::drop_in_place<<alloc::collections::vec_deque::drain::Drain<T,A> as core::ops::drop::Drop>::drop::DropGuard<i32,alloc::alloc::Global>>
	add rsp, 40
	ret

truncate:
	mov rax, qword ptr [rdi + 24]
	sub rax, rsi
	jbe .LBB2_2
	sub rsp, 40
	mov qword ptr [rdi + 24], rsi
	mov qword ptr [rsp], rdi
	mov qword ptr [rsp + 8], rax
	mov rcx, qword ptr [rdi]
	mov rdx, qword ptr [rdi + 16]
	add rdx, rsi
	xor edi, edi
	cmp rdx, rcx
	cmovae rdi, rcx
	mov qword ptr [rsp + 24], 0
	sub rdx, rdi
	mov rdi, rcx
	sub rdi, rdx
	lea r8, [rdx + rax]
	cmp rdi, rax
	cmovb r8, rcx
	sub rsi, rdx
	add rsi, r8
	mov qword ptr [rsp + 16], rsi
	mov qword ptr [rsp + 32], 0
	mov rdi, rsp
	call core::ptr::drop_in_place<<alloc::collections::vec_deque::drain::Drain<T,A> as core::ops::drop::Drop>::drop::DropGuard<i32,alloc::alloc::Global>>
	add rsp, 40

advance:
	mov rcx, qword ptr [rdi + 24]
	mov rax, rcx
	sub rax, rsi
	jbe .LBB3_1
	sub rsp, 40
	mov qword ptr [rdi + 24], 0
	mov qword ptr [rsp], rdi
	mov qword ptr [rsp + 8], rsi
	mov qword ptr [rsp + 16], 0
	mov qword ptr [rsp + 24], rax
	mov qword ptr [rsp + 32], rsi
	test rsi, rsi
	je .LBB3_6
	mov rax, qword ptr [rdi]
	mov rcx, qword ptr [rdi + 16]
	xor edx, edx
	cmp rcx, rax
	cmovae rdx, rax
	sub rcx, rdx
	mov rdx, rax
	sub rdx, rcx
	lea rdi, [rcx + rsi]
	cmp rdx, rsi
	cmovb rdi, rax
	sub rdi, rcx
	mov qword ptr [rsp + 16], rdi
	mov qword ptr [rsp + 32], 0
.LBB3_6:
	mov rdi, rsp
	call core::ptr::drop_in_place<<alloc::collections::vec_deque::drain::Drain<T,A> as core::ops::drop::Drop>::drop::DropGuard<i32,alloc::alloc::Global>>
	add rsp, 40
	ret
.LBB3_1:
	test rcx, rcx
	je .LBB3_3
	mov qword ptr [rdi + 24], 0
.LBB3_3:
	mov qword ptr [rdi + 16], 0
	ret

remove:
	sub rsp, 40
	cmp rdx, rsi
	jb .LBB4_5
	mov rax, qword ptr [rdi + 24]
	mov rcx, rax
	sub rcx, rdx
	jb .LBB4_6
	mov qword ptr [rdi + 24], rsi
	mov qword ptr [rsp], rdi
	sub rdx, rsi
	mov qword ptr [rsp + 8], rdx
	mov qword ptr [rsp + 16], rsi
	mov qword ptr [rsp + 24], rcx
	mov qword ptr [rsp + 32], rdx
	je .LBB4_4
	mov rax, qword ptr [rdi]
	mov rcx, qword ptr [rdi + 16]
	add rcx, rsi
	xor edi, edi
	cmp rcx, rax
	cmovae rdi, rax
	sub rcx, rdi
	mov rdi, rax
	sub rdi, rcx
	lea r8, [rcx + rdx]
	cmp rdi, rdx
	cmovb r8, rax
	sub rsi, rcx
	add rsi, r8
	mov qword ptr [rsp + 16], rsi
	mov qword ptr [rsp + 32], 0
.LBB4_4:
	mov rdi, rsp
	call core::ptr::drop_in_place<<alloc::collections::vec_deque::drain::Drain<T,A> as core::ops::drop::Drop>::drop::DropGuard<i32,alloc::alloc::Global>>
	add rsp, 40
	ret
.LBB4_5:
	lea rax, [rip + .L__unnamed_2]
	mov rdi, rsi
	mov rsi, rdx
	mov rdx, rax
	call qword ptr [rip + core::slice::index::slice_index_order_fail@GOTPCREL]
.LBB4_6:
	lea rcx, [rip + .L__unnamed_2]
	mov rdi, rdx
	mov rsi, rax
	mov rdx, rcx
	call qword ptr [rip + core::slice::index::slice_end_index_len_fail@GOTPCREL]

core::ptr::drop_in_place<<alloc::collections::vec_deque::drain::Drain<T,A> as core::ops::drop::Drop>::drop::DropGuard<i32,alloc::alloc::Global>>:
	push rbp
	push r15
	push r14
	push r13
	push r12
	push rbx
	sub rsp, 24
	mov rsi, qword ptr [rdi + 32]
	test rsi, rsi
	je .LBB0_2
	mov rax, qword ptr [rdi + 16]
	add rsi, rax
	jb .LBB0_45
.LBB0_2:
	mov r13, qword ptr [rdi]
	mov rbp, qword ptr [rdi + 8]
	mov rbx, qword ptr [r13 + 24]
	lea r12, [rbx + rbp]
	mov r15, qword ptr [rdi + 24]
	lea rsi, [r15 + r12]
	test rbx, rbx
	je .LBB0_10
	test r15, r15
	je .LBB0_42
	cmp rbx, r15
	jbe .LBB0_12
	mov r14, qword ptr [r13]
	mov rax, qword ptr [r13 + 16]
	add r12, rax
	xor ecx, ecx
	cmp r12, r14
	mov rdx, r14
	cmovb rdx, rcx
	sub r12, rdx
	add rbx, rax
	cmp rbx, r14
	cmovae rcx, r14
	sub rbx, rcx
	mov rcx, rbx
	sub rcx, r12
	je .LBB0_42
	mov rdi, qword ptr [r13 + 8]
	mov rax, rcx
	add rax, r14
	cmovae rax, rcx
	mov r8, r14
	sub r8, r12
	mov rcx, r14
	sub rcx, rbx
	mov rdx, r15
	sub rdx, r8
	mov qword ptr [rsp + 16], rsi
	jbe .LBB0_18
	cmp rax, r15
	jae .LBB0_24
	mov rdx, r15
	sub rdx, r8
	shl rdx, 2
	cmp r15, rcx
	jbe .LBB0_30
	sub r8, rcx
	mov qword ptr [rsp], rdi
	mov rax, qword ptr [rsp]
	lea rdi, [rax + 4*r8]
	mov rsi, qword ptr [rsp]
	mov qword ptr [rsp + 8], rcx
	mov r15, r8
	call qword ptr [rip + memmove@GOTPCREL]
	sub r14, r15
	mov rax, qword ptr [rsp]
	lea rsi, [rax + 4*r14]
	shl r15, 2
	mov rdi, qword ptr [rsp]
	mov rdx, r15
	call qword ptr [rip + memmove@GOTPCREL]
	mov rdi, qword ptr [rsp]
	lea rsi, [rdi + 4*r12]
	lea rdi, [rdi + 4*rbx]
	mov r15, qword ptr [rsp + 8]
	jmp .LBB0_36
.LBB0_10:
	test r15, r15
	je .LBB0_17
	mov rax, qword ptr [r13]
	sub rsi, rbp
	add rbp, qword ptr [r13 + 16]
	xor ecx, ecx
	cmp rbp, rax
	cmovae rcx, rax
	sub rbp, rcx
	mov qword ptr [r13 + 16], rbp
	jmp .LBB0_43
.LBB0_12:
	mov rdx, qword ptr [r13 + 16]
	mov r15, qword ptr [r13]
	lea rax, [rdx + rbp]
	xor ecx, ecx
	cmp rax, r15
	cmovae rcx, r15
	mov r12, rax
	sub r12, rcx
	mov rcx, r12
	sub rcx, rdx
	je .LBB0_41
	mov rdi, qword ptr [r13 + 8]
	mov rax, rcx
	add rax, r15
	cmovae rax, rcx
	mov r8, r15
	sub r8, rdx
	mov rcx, r15
	sub rcx, r12
	mov r14, rbx
	sub r14, r8
	mov qword ptr [rsp + 16], rsi
	jbe .LBB0_21
	cmp rax, rbx
	jae .LBB0_26
	mov qword ptr [rsp], rdx
	mov rdx, rbx
	sub rdx, r8
	shl rdx, 2
	cmp rbx, rcx
	jbe .LBB0_32
	sub r8, rcx
	mov rbx, rdi
	lea rdi, [rdi + 4*r8]
	mov rsi, rbx
	mov qword ptr [rsp + 8], rcx
	mov r14, r8
	call qword ptr [rip + memmove@GOTPCREL]
	sub r15, r14
	lea rsi, [rbx + 4*r15]
	shl r14, 2
	mov rdi, rbx
	mov rdx, r14
	call qword ptr [rip + memmove@GOTPCREL]
	mov rdi, rbx
	mov rax, qword ptr [rsp]
	lea rsi, [rbx + 4*rax]
	lea rdi, [rbx + 4*r12]
	mov rbx, qword ptr [rsp + 8]
	jmp .LBB0_40
.LBB0_17:
	xorps xmm0, xmm0
	movups xmmword ptr [r13 + 16], xmm0
	jmp .LBB0_44
.LBB0_18:
	mov r14, r15
	sub r14, rcx
	jbe .LBB0_28
	cmp rax, r15
	jae .LBB0_33
	lea rax, [rcx + r12]
	sub r15, rcx
	lea rsi, [rdi + 4*rax]
	shl r15, 2
	mov r14, rdi
	mov rdx, r15
	mov r15, rcx
	jmp .LBB0_31
.LBB0_21:
	mov r14, rbx
	sub r14, rcx
	jbe .LBB0_29
	cmp rax, rbx
	jae .LBB0_34
	lea rax, [rcx + rdx]
	sub rbx, rcx
	lea rsi, [rdi + 4*rax]
	shl rbx, 2
	mov r14, rdi
	mov r15, rdx
	mov rdx, rbx
	mov rbx, rcx
	call qword ptr [rip + memmove@GOTPCREL]
	mov rdi, r14
	lea rsi, [r14 + 4*r15]
	lea rdi, [r14 + 4*r12]
	jmp .LBB0_40
.LBB0_24:
	sub r15, rcx
	jbe .LBB0_35
	sub rcx, r8
	mov qword ptr [rsp + 8], rcx
	lea rsi, [rdi + 4*r12]
	mov r12, rdi
	lea rdi, [rdi + 4*rbx]
	lea rdx, [4*r8]
	mov r14, r8
	call qword ptr [rip + memmove@GOTPCREL]
	add r14, rbx
	lea rdi, [r12 + 4*r14]
	mov rbx, qword ptr [rsp + 8]
	lea rdx, [4*rbx]
	mov rsi, r12
	call qword ptr [rip + memmove@GOTPCREL]
	mov rdi, r12
	lea rsi, [r12 + 4*rbx]
	jmp .LBB0_36
.LBB0_26:
	sub rbx, rcx
	jbe .LBB0_37
	sub rcx, r8
	lea rsi, [rdi + 4*rdx]
	mov r15, rdi
	lea rdi, [rdi + 4*r12]
	lea rdx, [4*r8]
	mov r14, rcx
	mov qword ptr [rsp], r8
	call qword ptr [rip + memmove@GOTPCREL]
	add r12, qword ptr [rsp]
	lea rdi, [r15 + 4*r12]
	lea rdx, [4*r14]
	mov rsi, r15
	call qword ptr [rip + memmove@GOTPCREL]
	mov rdi, r15
	lea rsi, [r15 + 4*r14]
	jmp .LBB0_40
.LBB0_28:
	lea rsi, [rdi + 4*r12]
	lea rdi, [rdi + 4*rbx]
	jmp .LBB0_36
.LBB0_29:
	lea rsi, [rdi + 4*rdx]
	lea rdi, [rdi + 4*r12]
	jmp .LBB0_40
.LBB0_30:
	lea rax, [r8 + rbx]
	mov r14, rdi
	lea rdi, [rdi + 4*rax]
	mov rsi, r14
	mov r15, r8
.LBB0_31:
	call qword ptr [rip + memmove@GOTPCREL]
	mov rdi, r14
	lea rsi, [r14 + 4*r12]
	lea rdi, [r14 + 4*rbx]
	jmp .LBB0_36
.LBB0_32:
	lea rax, [r12 + r8]
	mov rbx, rdi
	lea rdi, [rdi + 4*rax]
	mov rsi, rbx
	mov r14, r8
	call qword ptr [rip + memmove@GOTPCREL]
	mov rdi, rbx
	mov rax, qword ptr [rsp]
	lea rsi, [rbx + 4*rax]
	jmp .LBB0_38
.LBB0_33:
	lea rsi, [rdi + 4*r12]
	mov r15, rdi
	lea rdi, [rdi + 4*rbx]
	lea rdx, [4*rcx]
	mov rbx, rcx
	call qword ptr [rip + memmove@GOTPCREL]
	mov rdi, r15
	add rbx, r12
	lea rsi, [r15 + 4*rbx]
	mov r15, r14
	jmp .LBB0_36
.LBB0_34:
	lea rsi, [rdi + 4*rdx]
	mov rbx, rdi
	lea rdi, [rdi + 4*r12]
	mov r15, rdx
	lea rdx, [4*rcx]
	mov r12, rcx
	call qword ptr [rip + memmove@GOTPCREL]
	mov rdi, rbx
	add r12, r15
	lea rsi, [rbx + 4*r12]
	jmp .LBB0_39
.LBB0_35:
	lea rsi, [rdi + 4*r12]
	mov r14, rdi
	lea rdi, [rdi + 4*rbx]
	mov r12, rdx
	lea rdx, [4*r8]
	mov r15, r8
	call qword ptr [rip + memmove@GOTPCREL]
	add r15, rbx
	mov rsi, r14
	lea rdi, [r14 + 4*r15]
	mov r15, r12
.LBB0_36:
	shl r15, 2
	mov rdx, r15
	call qword ptr [rip + memmove@GOTPCREL]
	mov rsi, qword ptr [rsp + 16]
	jmp .LBB0_42
.LBB0_37:
	lea rsi, [rdi + 4*rdx]
	mov rbx, rdi
	lea rdi, [rdi + 4*r12]
	lea rdx, [4*r8]
	mov r15, r8
	call qword ptr [rip + memmove@GOTPCREL]
	add r12, r15
	mov rsi, rbx
.LBB0_38:
	lea rdi, [rbx + 4*r12]
.LBB0_39:
	mov rbx, r14
.LBB0_40:
	shl rbx, 2
	mov rdx, rbx
	call qword ptr [rip + memmove@GOTPCREL]
	mov r15, qword ptr [r13]
	mov rax, qword ptr [r13 + 16]
	add rax, rbp
	mov rsi, qword ptr [rsp + 16]
.LBB0_41:
	xor ecx, ecx
	cmp rax, r15
	cmovae rcx, r15
	sub rax, rcx
	mov qword ptr [r13 + 16], rax
.LBB0_42:
	sub rsi, rbp
.LBB0_43:
	mov qword ptr [r13 + 24], rsi
.LBB0_44:
	add rsp, 24
	pop rbx
	pop r12
	pop r13
	pop r14
	pop r15
	pop rbp
	ret
.LBB0_45:
	lea rdx, [rip + .L__unnamed_1]
	mov rdi, rax
	call qword ptr [rip + core::slice::index::slice_index_order_fail@GOTPCREL]
```

after:
```asm
clear:
	movups xmmword ptr [rdi + 16], xmm0
	ret

truncate:
	cmp qword ptr [rdi + 24], rsi
	jbe .LBB2_4
	test rsi, rsi
	jne .LBB2_3
	mov qword ptr [rdi + 16], 0
.LBB2_3:
	mov qword ptr [rdi + 24], rsi
.LBB2_4:
	ret

advance:
	mov rcx, qword ptr [rdi + 24]
	mov rax, rcx
	sub rax, rsi
	jbe .LBB3_1
	mov rcx, qword ptr [rdi]
	add rsi, qword ptr [rdi + 16]
	xor edx, edx
	cmp rsi, rcx
	cmovae rdx, rcx
	sub rsi, rdx
	mov qword ptr [rdi + 16], rsi
	mov qword ptr [rdi + 24], rax
	ret
.LBB3_1:
	test rcx, rcx
	je .LBB3_3
	mov qword ptr [rdi + 24], 0
.LBB3_3:
	mov qword ptr [rdi + 16], 0
	ret

remove:
	push rbp
	push r15
	push r14
	push r13
	push r12
	push rbx
	push rax
	mov r15, rsi
	mov r14, rdx
	sub r14, rsi
	jb .LBB4_9
	mov rbx, rdi
	mov r12, qword ptr [rdi + 24]
	mov r13, r12
	sub r13, rdx
	jb .LBB4_10
	mov qword ptr [rbx + 24], r15
	mov rbp, r12
	sub rbp, r14
	test r15, r15
	je .LBB4_4
	cmp rbp, r15
	jne .LBB4_11
.LBB4_4:
	cmp r12, r14
	jne .LBB4_6
.LBB4_5:
	mov qword ptr [rbx + 16], 0
	jmp .LBB4_8
.LBB4_11:
	mov rdi, rbx
	mov rsi, r14
	mov rdx, r15
	mov rcx, r13
	call <<alloc::collections::vec_deque::drain::Drain<T,A> as core::ops::drop::Drop>::drop::DropGuard<T,A> as core::ops::drop::Drop>::drop::copy_data
	cmp r12, r14
	je .LBB4_5
.LBB4_6:
	cmp r13, r15
	jbe .LBB4_8
	mov rax, qword ptr [rbx]
	add r14, qword ptr [rbx + 16]
	xor ecx, ecx
	cmp r14, rax
	cmovae rcx, rax
	sub r14, rcx
	mov qword ptr [rbx + 16], r14
.LBB4_8:
	mov qword ptr [rbx + 24], rbp
	add rsp, 8
	pop rbx
	pop r12
	pop r13
	pop r14
	pop r15
	pop rbp
	ret
.LBB4_9:
	lea rax, [rip + .L__unnamed_1]
	mov rdi, r15
	mov rsi, rdx
	mov rdx, rax
	call qword ptr [rip + core::slice::index::slice_index_order_fail@GOTPCREL]
.LBB4_10:
	lea rax, [rip + .L__unnamed_1]
	mov rdi, rdx
	mov rsi, r12
	mov rdx, rax
	call qword ptr [rip + core::slice::index::slice_end_index_len_fail@GOTPCREL]

<<alloc::collections::vec_deque::drain::Drain<T,A> as core::ops::drop::Drop>::drop::DropGuard<T,A> as core::ops::drop::Drop>::drop::copy_data:
	push rbp
	push r15
	push r14
	push r13
	push r12
	push rbx
	push rax
	mov r14, rsi
	cmp rdx, rcx
	jae .LBB0_1
	mov r12, qword ptr [rdi]
	mov rax, qword ptr [rdi + 16]
	add r14, rax
	xor ecx, ecx
	cmp r14, r12
	cmovae rcx, r12
	sub r14, rcx
	mov r15, rdx
	mov r13, r14
	mov r14, rax
	mov rcx, r13
	sub rcx, r14
	je .LBB0_18
.LBB0_4:
	mov rdi, qword ptr [rdi + 8]
	mov rax, rcx
	add rax, r12
	cmovae rax, rcx
	mov rbx, r12
	sub rbx, r14
	mov rcx, r12
	sub rcx, r13
	mov rbp, r15
	sub rbp, rbx
	jbe .LBB0_5
	cmp rax, r15
	jae .LBB0_12
	mov rdx, r15
	sub rdx, rbx
	shl rdx, 2
	cmp r15, rcx
	jbe .LBB0_16
	sub rbx, rcx
	mov rbp, rdi
	lea rdi, [rdi + 4*rbx]
	mov r15, qword ptr [rip + memmove@GOTPCREL]
	mov rsi, rbp
	mov qword ptr [rsp], rcx
	call r15
	sub r12, rbx
	lea rsi, [4*r12]
	add rsi, rbp
	shl rbx, 2
	mov rdi, rbp
	mov rdx, rbx
	call r15
	mov rdi, rbp
	lea rsi, [4*r14]
	add rsi, rbp
	lea rdi, [4*r13]
	add rdi, rbp
	mov r15, qword ptr [rsp]
	jmp .LBB0_7
.LBB0_1:
	mov r15, rcx
	add r14, rdx
	mov r12, qword ptr [rdi]
	mov r13, qword ptr [rdi + 16]
	add r14, r13
	xor eax, eax
	cmp r14, r12
	mov rcx, r12
	cmovb rcx, rax
	sub r14, rcx
	add r13, rdx
	cmp r13, r12
	cmovae rax, r12
	sub r13, rax
	mov rcx, r13
	sub rcx, r14
	jne .LBB0_4
.LBB0_18:
	add rsp, 8
	pop rbx
	pop r12
	pop r13
	pop r14
	pop r15
	pop rbp
	ret
.LBB0_5:
	mov rbx, r15
	sub rbx, rcx
	jbe .LBB0_6
	cmp rax, r15
	jae .LBB0_9
	lea rax, [rcx + r14]
	sub r15, rcx
	lea rsi, [rdi + 4*rax]
	shl r15, 2
	mov rbx, rdi
	mov rdx, r15
	mov r15, rcx
	call qword ptr [rip + memmove@GOTPCREL]
	mov rdi, rbx
	lea rsi, [rbx + 4*r14]
	lea rdi, [rbx + 4*r13]
	jmp .LBB0_7
.LBB0_12:
	sub r15, rcx
	jbe .LBB0_13
	sub rcx, rbx
	lea rsi, [rdi + 4*r14]
	mov r12, rdi
	lea rdi, [rdi + 4*r13]
	lea rdx, [4*rbx]
	mov r14, qword ptr [rip + memmove@GOTPCREL]
	mov rbp, rcx
	call r14
	add rbx, r13
	lea rdi, [r12 + 4*rbx]
	lea rdx, [4*rbp]
	mov rsi, r12
	call r14
	mov rdi, r12
	lea rsi, [r12 + 4*rbp]
	jmp .LBB0_7
.LBB0_6:
	lea rsi, [rdi + 4*r14]
	lea rdi, [rdi + 4*r13]
	jmp .LBB0_7
.LBB0_16:
	lea rax, [rbx + r13]
	mov r15, rdi
	lea rdi, [rdi + 4*rax]
	mov rsi, r15
	call qword ptr [rip + memmove@GOTPCREL]
	mov rdi, r15
	lea rsi, [r15 + 4*r14]
	lea rdi, [r15 + 4*r13]
	mov r15, rbx
	jmp .LBB0_7
.LBB0_9:
	lea rsi, [rdi + 4*r14]
	mov r15, rdi
	lea rdi, [rdi + 4*r13]
	lea rdx, [4*rcx]
	mov r12, rcx
	call qword ptr [rip + memmove@GOTPCREL]
	mov rdi, r15
	add r12, r14
	lea rsi, [r15 + 4*r12]
	mov r15, rbx
	jmp .LBB0_7
.LBB0_13:
	lea rsi, [rdi + 4*r14]
	mov r14, rdi
	lea rdi, [rdi + 4*r13]
	lea rdx, [4*rbx]
	call qword ptr [rip + memmove@GOTPCREL]
	add rbx, r13
	mov rsi, r14
	lea rdi, [r14 + 4*rbx]
	mov r15, rbp
.LBB0_7:
	shl r15, 2
	mov rdx, r15
	add rsp, 8
	pop rbx
	pop r12
	pop r13
	pop r14
	pop r15
	pop rbp
	jmp qword ptr [rip + memmove@GOTPCREL]
```

</details>
2024-02-18 00:03:39 +00:00
Matthias Krüger cb371797d6
Rollup merge of #121149 - SebastianJL:patch-1, r=Mark-Simulacrum
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.
2024-02-17 18:47:41 +01:00
hi-rustin 6f1383cf5b Remove unnecessary unit binding
Signed-off-by: hi-rustin <rustin.liu@gmail.com>
2024-02-17 16:20:09 +08:00
Takashiidobe 1f2db3ddfc Add an example to demonstrate how Rc::into_inner works 2024-02-16 20:21:34 -05:00
Ben Kimock 7c2db703b0 Don't use mem::zeroed in vec::IntoIter 2024-02-16 10:44:39 -05:00
Lukas Markeffsky 5d989770f2 address review comments 2024-02-16 13:11:05 +01:00
Lukas Markeffsky b6702939f7 outline large copies 2024-02-16 13:10:52 +01:00
Lukas Markeffsky 1e3849aed0 reduce branchiness 2024-02-16 13:10:52 +01:00
Lukas Markeffsky 500ef67877 reduce amount of math 2024-02-16 13:10:52 +01:00
Lukas Markeffsky ec95d259e4 simplify codegen for trivially droppable types 2024-02-16 13:10:52 +01:00
bors 1be468815c Auto merge of #120486 - reitermarkus:use-generic-nonzero, r=dtolnay
Use generic `NonZero` internally.

Tracking issue: https://github.com/rust-lang/rust/issues/120257
2024-02-16 07:46:31 +00:00
Johannes Lade 17066870cd
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.
2024-02-15 17:33:37 +01:00
ltdk 290cbdf50e Add slice::try_range 2024-02-15 10:18:33 -05:00
Guillaume Gomez 472c820eb3
Rollup merge of #120505 - Amanieu:fix-btreemap-cursor-remove, r=m-ou-se
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).
2024-02-15 14:33:00 +01:00
Guillaume Gomez 9fdab38877
Rollup merge of #120449 - udoprog:document-unsized-rc-arc-from-raw, r=m-ou-se
Document requirements for unsized {Rc,Arc}::from_raw

This seems to be implied due to these types supporting operation-less unsized coercions. Taken together with the [established behavior of a wide to thin pointer cast](https://github.com/rust-lang/reference/pull/1451) it would enable unsafe downcasting of these containers.

Note that the term "data pointer" is adopted from https://github.com/rust-lang/rfcs/pull/3559

See also this [internals thread](https://internals.rust-lang.org/t/can-unsafe-smart-pointer-downcasts-be-correct/20229/2).
2024-02-15 14:32:59 +01:00
Markus Reiter a90cc05233
Replace `NonZero::<_>::new` with `NonZero::new`. 2024-02-15 08:09:42 +01:00
Markus Reiter 746a58d435
Use generic `NonZero` internally. 2024-02-15 08:09:42 +01:00
Oli Scherer 5d114f3c99
Rollup merge of #116387 - kpreid:wake-doc, r=cuviper
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).
2024-02-14 11:53:37 +01:00
Matthias Krüger 134de26337
Rollup merge of #120967 - LeoDog896:master, r=cuviper
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
2024-02-13 06:27:38 +01:00
Tristan F 0f53e720a8 docs: use correct link, use secondary example 2024-02-12 20:17:47 -05:00
Matthias Krüger 8305686126
Rollup merge of #120936 - ripytide:master, r=Amanieu
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.
2024-02-12 18:04:10 +01:00
Tristan F. 30f6665953 style: fmt 2024-02-12 14:43:19 +00:00
Tristan F 730560b982
docs: mention round-to-even in precision formatting 2024-02-12 08:20:13 -05:00
Matthias Krüger 251a09e151
Rollup merge of #110483 - tleibert:thin-box-try-new, r=dtolnay
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
2024-02-11 23:19:07 +01:00
ripytide f34d9da7db
fix intra-doc links 2024-02-11 20:26:05 +00:00
David Tolnay ea6944a065
Address ThinBox::try_new PR review 2024-02-11 11:28:01 -08:00
ripytide f415339052
fix incorrect doctest 2024-02-11 16:18:40 +00:00
ripytide 792fa24595
improve `btree_cursors` functions documentation 2024-02-11 15:51:07 +00:00
Matthias Krüger f4e6818bff
Rollup merge of #117740 - majaha:format_docs, r=joshtriplett
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.
2024-02-11 08:25:41 +01:00
Kevin Reid a6c91f0ae3 Remove the link. 2024-02-10 22:17:11 -08:00
Kevin Reid cef46f9e3d URL-encode chars in fragment. 2024-02-10 22:17:11 -08:00
Kevin Reid ccd6513c67 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).
2024-02-10 22:17:11 -08:00
bors 757b8efed4 Auto merge of #120712 - compiler-errors:async-closures-harmonize, r=oli-obk
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*`.
2024-02-10 07:15:15 +00:00
bors f4cfd87202 Auto merge of #120676 - Mark-Simulacrum:bootstrap-bump, r=clubby789
Bump bootstrap compiler to just-built 1.77 beta

https://forge.rust-lang.org/release/process.html#master-bootstrap-update-t-2-day-tuesday
2024-02-09 18:09:02 +00:00
Ben Kimock 88d6e9f868 Reduce use of NonNull::new_unchecked in library/ 2024-02-08 11:52:16 -05:00
Mark Rousskov 8043821b3a Bump version placeholders 2024-02-08 07:43:38 -05:00
Michael Goulet 0dd40786b5 Harmonize blanket implementations for AsyncFn* traits 2024-02-06 17:20:40 +00:00
Matthias Krüger 80e8c7e125
Rollup merge of #118960 - tvallotton:local_waker, r=Mark-Simulacrum
Add LocalWaker and ContextBuilder types to core, and LocalWake trait to alloc.

Implementation for  #118959.
2024-02-05 11:07:26 +01:00
Matthias Krüger 13e84f2a3d
Rollup merge of #113833 - WiktorPrzetacznik:master, r=dtolnay
`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)
2024-02-05 11:07:25 +01:00
Matthias Krüger 9838e943f3
Rollup merge of #120458 - rytheo:cstr-conversion-doc, r=Mark-Simulacrum
Document `&CStr` to `CString` conversion

Related to #51430
2024-02-05 06:37:14 +01:00
Nadrieril 03daaa6f07
Rollup merge of #120355 - the8472:doc-vec-fromiter, r=cuviper
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.
2024-01-31 12:10:50 +01:00
the8472 39dc3153c5 Apply suggestions from code review
Co-authored-by: Josh Stone <cuviper@gmail.com>
2024-01-30 22:37:07 +01:00
The 8472 c780fe6b27 document `FromIterator for Vec` allocation behaviors 2024-01-30 22:37:07 +01:00
Amanieu d'Antras adb7607189 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).
2024-01-30 17:51:20 +00:00
Guillaume Gomez a5aa355ab3
Rollup merge of #120445 - Nemo157:arc-plug, r=Mark-Simulacrum
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.
2024-01-30 16:57:50 +01:00
Dylan DPC 4528b37196
Rollup merge of #120266 - steffahn:a_rc_into_inner_docs, r=Mark-Simulacrum
Improve documentation for [A]Rc::into_inner

General improvements, and also aims to better encourage the reader to actually check out Arc::try_unwrap.

This addresses concerns from https://github.com/rust-lang/rust/issues/106894#issuecomment-1905627234.

Rendered:

![Screenshot_20240123_114436](https://github.com/rust-lang/rust/assets/3986214/68896d62-13e0-4f3a-8073-91d8e77c5554)
![Screenshot_20240123_114455](https://github.com/rust-lang/rust/assets/3986214/dc58e4bd-dd7f-40b1-bc50-fd6200dde593)
2024-01-29 12:56:52 +00:00
Ryan Lowe 6aec11afbc Document From<&CStr> for CString 2024-01-28 16:53:57 -05:00
Wim Looman 6837b812e6
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.
2024-01-28 18:33:34 +01:00
John-John Tedro bdbbf04a03 Fix doctest 2024-01-28 18:25:21 +01:00
John-John Tedro eebc720757 Replicate documentation in {Rc,Arc}::from_raw_in 2024-01-28 17:00:52 +01:00
John-John Tedro d63384d689 Fix doctest 2024-01-28 16:38:38 +01:00
John-John Tedro 23c83fab2b Tidy up 2024-01-28 16:12:09 +01:00
John-John Tedro d4adb3af58 Add examples for unsized {Rc,Arc}::from_raw 2024-01-28 16:07:07 +01:00
John-John Tedro 57e0dea178 Document requirements for unsized {Rc,Arc}::from_raw 2024-01-28 15:57:08 +01:00
Matthias Krüger 092ea4ba19
Rollup merge of #113489 - tguichaoua:cow_from_array, r=dtolnay
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
}
```
2024-01-26 23:15:48 +01:00
Matthias Krüger c9ab37bf4f
Rollup merge of #103522 - Dylan-DPC:76118/array-methods-stab, r=dtolnay
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
2024-01-26 23:15:47 +01:00
Matthias Krüger d1c3ddee2e
Rollup merge of #120372 - bjorn3:fix_outdated_comment, r=Nilstrieb
Fix outdated comment on Box

Caught by `@vi` in https://github.com/rust-lang/rust/pull/113960#discussion_r1454278520
2024-01-26 14:43:33 +01:00
Matthias Krüger 772e80a650
Rollup merge of #119917 - Zalathar:split-off, r=cuviper
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.
2024-01-26 14:43:30 +01:00
Matthias Krüger a5b60c941e
Rollup merge of #117678 - niklasf:stabilize-slice_group_by, r=dtolnay
Stabilize `slice_group_by`

Renamed "group by" to "chunk by" a per #80552.

Newly stable items:

* `core::slice::ChunkBy`
* `core::slice::ChunkByMut`
* `[T]::chunk`
* `[T]::chunk_by`

Closes #80552.
2024-01-26 14:43:29 +01:00
bjorn3 1f994c7695 Fix outdated comment on Box 2024-01-26 12:15:46 +00:00
Matthias Krüger 912877d009
Rollup merge of #119466 - Sky9x:str_from_raw_parts, r=dtolnay
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.
2024-01-26 06:36:37 +01:00
David Tolnay f94a94227c
Export core::str::from_raw_parts{,_mut} into alloc::str and std::str 2024-01-25 18:11:54 -08:00
Matthias Krüger 37f02320bc
Rollup merge of #118208 - Amanieu:btree_cursor2, r=dtolnay
Rewrite the BTreeMap cursor API using gaps

Tracking issue: #107540

Currently, a `Cursor` points to a single element in the tree, and allows moving to the next or previous element while mutating the tree. However this was found to be confusing and hard to use.

This PR completely refactors cursors to instead point to a gap between two elements in the tree. This eliminates the need for a "ghost" element that exists after the last element and before the first one. Additionally, `upper_bound` and `lower_bound` now have a much clearer meaning.

The ability to mutate keys is also factored out into a separate `CursorMutKey` type which is unsafe to create. This makes the API easier to use since it avoids duplicated versions of each method with and without key mutation.

API summary:

```rust
impl<K, V> BTreeMap<K, V> {
    fn lower_bound<Q>(&self, bound: Bound<&Q>) -> Cursor<'_, K, V>
    where
        K: Borrow<Q> + Ord,
        Q: Ord;
    fn lower_bound_mut<Q>(&mut self, bound: Bound<&Q>) -> CursorMut<'_, K, V>
    where
        K: Borrow<Q> + Ord,
        Q: Ord;
    fn upper_bound<Q>(&self, bound: Bound<&Q>) -> Cursor<'_, K, V>
    where
        K: Borrow<Q> + Ord,
        Q: Ord;
    fn upper_bound_mut<Q>(&mut self, bound: Bound<&Q>) -> CursorMut<'_, K, V>
    where
        K: Borrow<Q> + Ord,
        Q: Ord;
}

struct Cursor<'a, K: 'a, V: 'a>;

impl<'a, K, V> Cursor<'a, K, V> {
    fn next(&mut self) -> Option<(&'a K, &'a V)>;
    fn prev(&mut self) -> Option<(&'a K, &'a V)>;
    fn peek_next(&self) -> Option<(&'a K, &'a V)>;
    fn peek_prev(&self) -> Option<(&'a K, &'a V)>;
}

struct CursorMut<'a, K: 'a, V: 'a>;

impl<'a, K, V> CursorMut<'a, K, V> {
    fn next(&mut self) -> Option<(&K, &mut V)>;
    fn prev(&mut self) -> Option<(&K, &mut V)>;
    fn peek_next(&mut self) -> Option<(&K, &mut V)>;
    fn peek_prev(&mut self) -> Option<(&K, &mut V)>;

    unsafe fn insert_after_unchecked(&mut self, key: K, value: V);
    unsafe fn insert_before_unchecked(&mut self, key: K, value: V);
    fn insert_after(&mut self, key: K, value: V) -> Result<(), UnorderedKeyError>;
    fn insert_before(&mut self, key: K, value: V) -> Result<(), UnorderedKeyError>;
    fn remove_next(&mut self) -> Option<(K, V)>;
    fn remove_prev(&mut self) -> Option<(K, V)>;

    fn as_cursor(&self) -> Cursor<'_, K, V>;

    unsafe fn with_mutable_key(self) -> CursorMutKey<'a, K, V, A>;
}

struct CursorMutKey<'a, K: 'a, V: 'a>;

impl<'a, K, V> CursorMut<'a, K, V> {
    fn next(&mut self) -> Option<(&mut K, &mut V)>;
    fn prev(&mut self) -> Option<(&mut K, &mut V)>;
    fn peek_next(&mut self) -> Option<(&mut K, &mut V)>;
    fn peek_prev(&mut self) -> Option<(&mut K, &mut V)>;

    unsafe fn insert_after_unchecked(&mut self, key: K, value: V);
    unsafe fn insert_before_unchecked(&mut self, key: K, value: V);
    fn insert_after(&mut self, key: K, value: V) -> Result<(), UnorderedKeyError>;
    fn insert_before(&mut self, key: K, value: V) -> Result<(), UnorderedKeyError>;
    fn remove_next(&mut self) -> Option<(K, V)>;
    fn remove_prev(&mut self) -> Option<(K, V)>;

    fn as_cursor(&self) -> Cursor<'_, K, V>;

    unsafe fn with_mutable_key(self) -> CursorMutKey<'a, K, V, A>;
}

struct UnorderedKeyError;
```
2024-01-25 17:39:26 +01:00
bors dfe53afaeb Auto merge of #119433 - taiki-e:rc-uninit-ref, r=Nilstrieb
rc,sync: Do not create references to uninitialized values

Closes #119241

r? `@RalfJung`
2024-01-23 16:43:45 +00:00
Frank Steffahn ab938b9acb Improve documentation for [A]Rc::into_inner
General improvements, and also aims to better encourage the reader
to actually check out Arc::try_unwrap.
2024-01-23 11:38:15 +01:00
bors e35a56d96f Auto merge of #119892 - joboet:libs_use_assert_unchecked, r=Nilstrieb,cuviper
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
2024-01-23 06:45:58 +00:00
Matthias Krüger 97bcf0da7c
Rollup merge of #119801 - zachs18:zachs18-patch-1, r=steffahn,Nilstrieb
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>
2024-01-22 16:54:57 +01:00
bors 6fff796eac Auto merge of #120196 - matthiaskrgr:rollup-id2zocf, r=matthiaskrgr
Rollup of 8 pull requests

Successful merges:

 - #120005 (Update Readme)
 - #120045 (Un-hide `iter::repeat_n`)
 - #120128 (Make stable_mir::with_tables sound)
 - #120145 (fix: Drop guard was deallocating with the incorrect size)
 - #120158 (`rustc_mir_dataflow`: Restore removed exports)
 - #120167 (Capture the rationale for `-Zallow-features=` in bootstrap.py)
 - #120174 (Warn users about limited review for tier 2 and 3 code)
 - #120180 (Document some alternatives to `Vec::split_off`)

Failed merges:

 - #120171 (Fix assume and assert in jump threading)

r? `@ghost`
`@rustbot` modify labels: rollup
2024-01-22 08:56:22 +00:00
Matthias Krüger 3eb7fe32a1
Rollup merge of #120180 - Zalathar:vec-split-off-alternatives, r=dtolnay
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.
2024-01-21 12:28:55 +01:00
Matthias Krüger 4a941d384d
Rollup merge of #120145 - the8472:fix-inplace-dest-drop, r=cuviper
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.
2024-01-21 12:28:53 +01:00
bors fa404339c9 Auto merge of #85528 - the8472:iter-markers, r=dtolnay
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)
```
2024-01-21 11:17:46 +00:00
Zalathar 6f1944d394 Document some alternatives to `Vec::split_off` 2024-01-21 11:56:55 +11:00
Guillaume Gomez b917753d79
Rollup merge of #120116 - the8472:only-same-alignments, r=cuviper
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.
2024-01-20 20:06:35 +01:00