Commit Graph

299 Commits

Author SHA1 Message Date
Mark Rousskov f1ae5314be Avoid reloading Vec::len across grow_one in push
This saves an extra load from memory.
2024-04-20 21:07:00 -04:00
Matthias Krüger 21deaed4a1 Rollup merge of #122201 - coolreader18:doc-clone_from, r=dtolnay
Document overrides of `clone_from()` in core/std

As mentioned in https://github.com/rust-lang/rust/pull/96979#discussion_r1379502413

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".

I reused some of the wording over and over for similar impls, but I'm not sure that the wording is actually *good*. Would appreciate feedback about that.

Also, now some of these seem to provide pretty specific guarantees about behavior (e.g. will reuse the exact same allocation iff the len is the same), but I was basing it off of the docs for [`Box::clone_from`](https://doc.rust-lang.org/1.75.0/std/boxed/struct.Box.html#method.clone_from-1) - I'm not sure if providing those strong guarantees is actually good or not.
2024-04-17 18:01:37 +02:00
Ben Kimock f7d54fa6cb Avoid more NonNull-raw-NonNull roundtrips in Vec 2024-04-12 18:14:29 -04:00
Cai Bear aba592d09c Rename reserve_for_push to grow_one and fix comment. 2024-03-28 16:38:01 -07:00
Cai Bear 18d390883e Remove len argument from RawVec::reserve_for_push because it's always equal to capacity. Also make Vec::insert use reserve_for_push. 2024-03-28 16:21:54 -07:00
Matthias Krüger 19a40ec5bf Rollup merge of #123107 - avandesa:vec_pop_if, r=joboet
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?
2024-03-27 05:21:18 +01:00
Alex van de Sandt 07d3806eb1 Implement Vec::pop_if 2024-03-26 18:25:24 -04:00
Michael Goulet b56279569b Require DerefPure for patterns 2024-03-25 19:39:45 -04: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
Pierre Allix 23e1b570d7 Improve wording of Vec::swap_remove 2024-03-17 18:27:02 +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
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 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
Kornel 78fb977d6b try_with_capacity for Vec, VecDeque, String
#91913
2024-03-01 18:24:02 +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) a1b93e8fed Rearrange Vec::from_raw_parts{,_in} doc argument order to match code argument order 2024-02-26 19:32:17 +00:00
Jacob Asper 74151cbbf0 Make push docs more vague 2024-02-25 02:43:21 -05: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
Jacob Asper bc52e5d4de Fix error in push docs
Copying is O(n)—not the memory allocation
2024-02-18 17:55:52 -05: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
Ben Kimock 88d6e9f868 Reduce use of NonNull::new_unchecked in library/ 2024-02-08 11:52:16 -05: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
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
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 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
Zalathar 6f1944d394 Document some alternatives to Vec::split_off 2024-01-21 11:56:55 +11:00
The 8472 5796b3c167 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.
2024-01-19 23:05:30 +01:00
invpt 35a9fc3472 Clarify docs for Vec::into_boxed_slice, Vec::shrink_to_fit 2024-01-18 18:01:36 -05:00
joboet fa9a911a57 libs: use assert_unchecked instead of intrinsic 2024-01-13 20:10:00 +01:00
Zalathar a655558b38 Remove special-case handling of vec.split_off(0) 2024-01-13 17:21:54 +11:00
The 8472 93b34a5ffa mark vec::IntoIter pointers as !nonnull 2024-01-07 03:44:04 +01:00
Gurinder Singh e3aca01343 Italicise "bytes" in the docs of some Vec methods
because on a cursory read it's easy to miss that the limit is
in terms of bytes not no. of elements. The italics should help
with that.
2023-12-29 09:53:29 +05:30
bors e9013ac0e4 Auto merge of #118273 - AngelicosPhosphoros:dedup_2_loops_version_77772_2, r=the8472
Split `Vec::dedup_by` into 2 cycles

First cycle runs until we found 2 same elements, second runs after if there any found in the first one. This allows to avoid any memory writes until we found an item which we want to remove.

This leads to significant performance gains if all `Vec` items are kept: -40% on my benchmark with unique integers.

Results of benchmarks before implementation (including new benchmark where nothing needs to be removed):
 *   vec::bench_dedup_all_100                 74.00ns/iter  +/- 13.00ns
 *   vec::bench_dedup_all_1000               572.00ns/iter +/- 272.00ns
 *   vec::bench_dedup_all_100000              64.42µs/iter  +/- 19.47µs
 *   __vec::bench_dedup_none_100                67.00ns/iter  +/- 17.00ns__
 *   __vec::bench_dedup_none_1000              662.00ns/iter  +/- 86.00ns__
 *   __vec::bench_dedup_none_10000               9.16µs/iter   +/- 2.71µs__
 *   __vec::bench_dedup_none_100000             91.25µs/iter   +/- 1.82µs__
 *   vec::bench_dedup_random_100             105.00ns/iter  +/- 11.00ns
 *   vec::bench_dedup_random_1000            781.00ns/iter  +/- 10.00ns
 *   vec::bench_dedup_random_10000             9.00µs/iter   +/- 5.62µs
 *   vec::bench_dedup_random_100000          449.81µs/iter  +/- 74.99µs
 *   vec::bench_dedup_slice_truncate_100     105.00ns/iter  +/- 16.00ns
 *   vec::bench_dedup_slice_truncate_1000      2.65µs/iter +/- 481.00ns
 *   vec::bench_dedup_slice_truncate_10000    18.33µs/iter   +/- 5.23µs
 *   vec::bench_dedup_slice_truncate_100000  501.12µs/iter  +/- 46.97µs

Results after implementation:
 *   vec::bench_dedup_all_100                 75.00ns/iter   +/- 9.00ns
 *   vec::bench_dedup_all_1000               494.00ns/iter +/- 117.00ns
 *   vec::bench_dedup_all_100000              58.13µs/iter   +/- 8.78µs
 *   __vec::bench_dedup_none_100                52.00ns/iter  +/- 22.00ns__
 *   __vec::bench_dedup_none_1000              417.00ns/iter +/- 116.00ns__
 *   __vec::bench_dedup_none_10000               4.11µs/iter +/- 546.00ns__
 *   __vec::bench_dedup_none_100000             40.47µs/iter   +/- 5.36µs__
 *   vec::bench_dedup_random_100              77.00ns/iter  +/- 15.00ns
 *   vec::bench_dedup_random_1000            681.00ns/iter  +/- 86.00ns
 *   vec::bench_dedup_random_10000            11.66µs/iter   +/- 2.22µs
 *   vec::bench_dedup_random_100000          469.35µs/iter  +/- 20.53µs
 *   vec::bench_dedup_slice_truncate_100     100.00ns/iter   +/- 5.00ns
 *   vec::bench_dedup_slice_truncate_1000      2.55µs/iter +/- 224.00ns
 *   vec::bench_dedup_slice_truncate_10000    18.95µs/iter   +/- 2.59µs
 *   vec::bench_dedup_slice_truncate_100000  492.85µs/iter  +/- 72.84µs

Resolves #77772

P.S. Note that this is same PR as #92104 I just missed review then forgot about it.
Also, I cannot reopen that pull request so I am creating a new one.
I responded to remaining questions directly by adding commentaries to my code.
2023-12-05 21:40:02 +00:00
AngelicosPhosphoros 964df019d2 Split Vec::dedup_by into 2 cycles
First cycle runs until we found 2 same elements, second runs after if there any found in the first one. This allows to avoid any memory writes until we found an item which we want to remove.

This leads to significant performance gains if all `Vec` items are kept: -40% on my benchmark with unique integers.

Results of benchmarks before implementation (including new benchmark where nothing needs to be removed):
 *   vec::bench_dedup_all_100                 74.00ns/iter  +/- 13.00ns
 *   vec::bench_dedup_all_1000               572.00ns/iter +/- 272.00ns
 *   vec::bench_dedup_all_100000              64.42µs/iter  +/- 19.47µs
 *   __vec::bench_dedup_none_100                67.00ns/iter  +/- 17.00ns__
 *   __vec::bench_dedup_none_1000              662.00ns/iter  +/- 86.00ns__
 *   __vec::bench_dedup_none_10000               9.16µs/iter   +/- 2.71µs__
 *   __vec::bench_dedup_none_100000             91.25µs/iter   +/- 1.82µs__
 *   vec::bench_dedup_random_100             105.00ns/iter  +/- 11.00ns
 *   vec::bench_dedup_random_1000            781.00ns/iter  +/- 10.00ns
 *   vec::bench_dedup_random_10000             9.00µs/iter   +/- 5.62µs
 *   vec::bench_dedup_random_100000          449.81µs/iter  +/- 74.99µs
 *   vec::bench_dedup_slice_truncate_100     105.00ns/iter  +/- 16.00ns
 *   vec::bench_dedup_slice_truncate_1000      2.65µs/iter +/- 481.00ns
 *   vec::bench_dedup_slice_truncate_10000    18.33µs/iter   +/- 5.23µs
 *   vec::bench_dedup_slice_truncate_100000  501.12µs/iter  +/- 46.97µs

Results after implementation:
 *   vec::bench_dedup_all_100                 75.00ns/iter   +/- 9.00ns
 *   vec::bench_dedup_all_1000               494.00ns/iter +/- 117.00ns
 *   vec::bench_dedup_all_100000              58.13µs/iter   +/- 8.78µs
 *   __vec::bench_dedup_none_100                52.00ns/iter  +/- 22.00ns__
 *   __vec::bench_dedup_none_1000              417.00ns/iter +/- 116.00ns__
 *   __vec::bench_dedup_none_10000               4.11µs/iter +/- 546.00ns__
 *   __vec::bench_dedup_none_100000             40.47µs/iter   +/- 5.36µs__
 *   vec::bench_dedup_random_100              77.00ns/iter  +/- 15.00ns
 *   vec::bench_dedup_random_1000            681.00ns/iter  +/- 86.00ns
 *   vec::bench_dedup_random_10000            11.66µs/iter   +/- 2.22µs
 *   vec::bench_dedup_random_100000          469.35µs/iter  +/- 20.53µs
 *   vec::bench_dedup_slice_truncate_100     100.00ns/iter   +/- 5.00ns
 *   vec::bench_dedup_slice_truncate_1000      2.55µs/iter +/- 224.00ns
 *   vec::bench_dedup_slice_truncate_10000    18.95µs/iter   +/- 2.59µs
 *   vec::bench_dedup_slice_truncate_100000  492.85µs/iter  +/- 72.84µs

Resolves #77772
2023-12-05 21:01:00 +01:00
r0cky c751bfa015 Add proper cfgs 2023-11-28 09:02:34 +08:00
ltdk 8337e86b28 Add insta-stable std::hash::{DefaultHasher, RandomState} exports 2023-11-02 20:35:20 -04:00
Ben Kimock 2e7364a586 Increase the reach of panic_immediate_abort 2023-10-29 09:31:07 -04:00
Arthur Carcano 0bcac8a7f2 Add invariant to Vec::pop that len < cap if pop successful
Fixes: https://github.com/rust-lang/rust/issues/114334
2023-10-16 18:49:25 +02:00
Mark Rousskov ea1066d0be Bump to latest beta 2023-10-08 19:57:43 -04:00
Mark Rousskov 787d32324c Bump version placeholders 2023-10-03 20:26:36 -04:00
bors aeaa5c30e5 Auto merge of #111278 - EFanZh:implement-from-array-refs-for-vec, r=dtolnay
Implement `From<{&,&mut} [T; N]>` for `Vec<T>` where `T: Clone`

Currently, if `T` implements `Clone`, we can create a `Vec<T>` from an `&[T]` or an `&mut [T]`, can we also support creating a `Vec<T>` from an `&[T; N]` or an `&mut [T; N]`? Also, do I need to add `#[inline]` to the implementation?

ACP: rust-lang/libs-team#220. [Accepted]

Closes #100880.
2023-09-28 04:26:40 +00:00
mxnkarou d1ff5e174b edit std::vec::Vec::truncate docs 2023-09-16 15:46:31 +02:00
bors 635c4a5e61 Auto merge of #114494 - est31:extend_useless_ptr_null_checks, r=jackh726
Make useless_ptr_null_checks smarter about some std functions

This teaches the `useless_ptr_null_checks` lint that some std functions can't ever return null pointers, because they need to point to valid data, get references as input, etc.

This is achieved by introducing an `#[rustc_never_returns_null_ptr]` attribute and adding it to these std functions (gated behind bootstrap `cfg_attr`).

Later on, the attribute could maybe be used to tell LLVM that the returned pointer is never null. I don't expect much impact of that though, as the functions are pretty shallow and usually the input data is already never null.

Follow-up of PR #113657

Fixes #114442
2023-09-16 03:40:20 +00:00
bors cedbe5c715 Auto merge of #113859 - Manishearth:vec-as-mut-ptr-stacked-borrow, r=dtolnay
Add note that Vec::as_mut_ptr() does not materialize a reference to the internal buffer

See discussion on https://github.com/thomcc/rust-typed-arena/issues/62 and [t-opsem](https://rust-lang.zulipchat.com/#narrow/stream/136281-t-opsem/topic/is.20this.20typed_arena.20code.20sound.20under.20stacked.2Ftree.20borrows.3F)

This method already does the correct thing here, but it is worth guaranteeing that it does so it can be used more freely in unsafe code without having to worry about potential Stacked/Tree Borrows violations. This moves one more unsafe usage pattern from the "very likely sound but technically not fully defined" box into "definitely sound", and currently our surface area of the latter is woefully small.

I'm not sure how best to word this, opening this PR as a way to start discussion.
2023-08-29 06:04:55 +00:00