Commit graph

606 commits

Author SHA1 Message Date
Zachary S
890e50de69 Stabilize feature(push_mut) 2026-01-28 10:02:49 -06:00
bors
873d4682c7 Auto merge of #151337 - the8472:bail-before-memcpy2, r=Mark-Simulacrum
optimize `vec.extend(slice.to_vec())`, take 2

Redoing https://github.com/rust-lang/rust/pull/130998
It was reverted in https://github.com/rust-lang/rust/pull/151150 due to flakiness. I have traced this to layout randomization perturbing the test (the failure reproduces locally with layout randomization), which is now excluded.
2026-01-25 19:45:35 +00:00
The 8472
2b8f4a562f avoid phi node for pointers flowing into Vec appends 2026-01-18 21:03:14 +01:00
cyrgani
69da4016aa remove reason = "new API" from #[unstable(...)] 2026-01-16 13:34:34 +00:00
Jieyou Xu
cd79ff2e2c
Revert "avoid phi node for pointers flowing into Vec appends #130998"
This reverts PR <https://github.com/rust-lang/rust/pull/130998> because
the added test seems to be flaky / non-deterministic, and has been
failing in unrelated PRs during merge CI.
2026-01-15 09:37:16 +08:00
The 8472
468eb45b3f avoid phi node for pointers flowing into Vec appends 2026-01-12 02:54:30 +01:00
Scott McMurray
5932078c79 Stop emitting UbChecks on every Vec→Slice
Spotted this in PR148766's test changes.  It doesn't seem like this ubcheck would catch anything useful; let's see if skipping it helps perf.
2026-01-08 17:14:02 -08:00
bors
74fd7516da Auto merge of #147893 - fee1-dead-contrib:constheapheapheap, r=oli-obk
`Vec::push` in consts MVP

Example:

```rust
const X: &'static [u32] = {
    let mut v = Vec::with_capacity(6);
    let mut x = 1;
    while x < 42 {
        v.push(x);
        x *= 2;
    }
    assert!(v.len() == 6);
    v.const_make_global()
};

assert_eq!([1, 2, 4, 8, 16, 32], X);
```

Oh this is fun...

* We split out the implementation of `Global` such that it calls `intrinsics::const_allocate` and `intrinsics::const_deallocate` during compile time. This is achieved using `const_eval_select`
* This allows us to `impl const Allocator for Global`
* We then constify everything necessary for `Vec::with_capacity` and `Vec::push`.
* Added `Vec::const_make_global` to leak and intern the final value via `intrinsics::const_make_global`. If we see any pointer in the final value of a `const` that did not call `const_make_global`, we error as implemented in rust-lang/rust#143595.

r? `@rust-lang/wg-const-eval`

To-do for me:
* [x] Assess the rustdoc impact of additional bounds in the method
* [x] ~~Increase test coverage~~ I think this is enough for an unstable feature.
2026-01-06 11:39:17 +00:00
bors
bd33b83cfd Auto merge of #149784 - fereidani:retain_mut, r=joboet
Improve alloc `Vec::retain_mut` performance

Hi,

While reading the rustc source code, I noticed it uses `smallvec` and `thin-vec` in many places. I started reviewing those crates, optimized their `retain_mut` implementation, and then realized they were using the exact same algorithm as `alloc::vec::Vec` with less unsafe  So now I’m back here with a PR for the standard library 😂.

In my benchmarks, this version is noticeably faster when `retain_mut` actually removes elements (thanks to fewer pointer operations, it just advances `write_index`), while performing identically to the current implementation when nothing is removed.

Let’s see if bors likes this change or not.
2026-01-05 14:55:14 +00:00
Khashayar Fereidani
bd79ea1b74 Improve and optimize retain_mut implementation 2026-01-05 13:18:41 +03:30
bors
e29fcf45e4 Auto merge of #150674 - matthiaskrgr:rollup-tnkgbcx, r=matthiaskrgr
Rollup of 5 pull requests

Successful merges:

 - rust-lang/rust#150554 (test: add regression cases for valtree hashing ICE)
 - rust-lang/rust#150597 (make specialization of `Vec::extend` and `VecDeque::extend_front` work for vec::IntoIter with any `Allocator`, not just `Global`)
 - rust-lang/rust#150619 (alloc: Move Cow impl to existing ones)
 - rust-lang/rust#150660 (THIR pattern building: Pass HIR nodes instead of loose types/spans)
 - rust-lang/rust#150671 (miri subtree update)

r? `@ghost`
`@rustbot` modify labels: rollup
2026-01-04 16:58:33 +00:00
Marijn Schouten
47798e261e vec in-place-drop: avoid creating an intermediate slice 2026-01-03 12:08:40 +00:00
Antoni Spaanderman
9a170fedd7
make specialization of Vec::extend and VecDeque::extend_front work for vec::IntoIter with any Allocator, not just Global 2026-01-02 16:15:40 +01:00
Deadbeef
a913065d80 fix rustfmt and bless tidy/tests 2026-01-01 19:17:11 -05:00
Deadbeef
cf61cbcb07 Move into const impl blocks 2026-01-01 19:17:11 -05:00
Deadbeef
47864e80cb address review comments; fix CI 2026-01-01 19:17:11 -05:00
Deadbeef
3982d3e706 Vec::push in consts MVP 2026-01-01 19:17:11 -05:00
Jeremy Smart
0763954226
add VecDeque::splice 2025-12-29 13:25:56 -05:00
Boxy Uwu
90a33f69f4 replace version placeholder 2025-12-19 15:04:30 -08:00
Chris Denton
735c45eda4
Rollup merge of #149272 - DrAsu33:fix-vec-iter-zst-alignment-148682, r=Mark-Simulacrum
Fix vec iter zst alignment

Closes rust-lang/rust#148682
2025-12-14 09:18:28 +00:00
Esteban Küber
0488690d3e Use let...else instead of match foo { ... _ => return }; and if let ... else return in std 2025-12-09 23:35:14 +00:00
DrAsu33
34392a99c0 Fix(alloc): Correctly handle ZST alignment for IntoIter::nth_back
This commit consolidates all changes, including the core logic fix for IntoIter::nth_back and the addition of the Miri regression test in `library/alloctests/tests/vec.rs`, to prevent Undefined Behavior (UB) when dealing with highly-aligned Zero-Sized Types.
2025-12-09 07:56:26 +00:00
EFanZh
c5113ca1e2 Implement Vec::from_fn 2025-12-06 12:55:15 +08:00
Matthias Krüger
4d08c33fc1
Rollup merge of #148662 - leftmostcat:document-isize-limit, r=joboet
alloc: Document panics when allocations will exceed max

Document panics in `String` and `Vec` due to capacity overflowing `isize::MAX`. Correct outdated claims of `usize::MAX` limit.

Fixes https://github.com/rust-lang/rust/issues/148598.

Ping `@lolbinarycat`
2025-12-05 16:17:05 +01:00
Mads Marquart
1111730c57 Add doc aliases list and vector to Vec 2025-11-23 05:58:15 +01:00
Matthias Krüger
cd4ce66e50
Rollup merge of #147035 - joboet:extract_if_debug, r=tgross35
alloc: fix `Debug` implementation of `ExtractIf`

I noticed this while reviewing rust-lang/rust#141032. Calling `get` on the inner `Vec` never returns `Some` as the `Vec`'s length is temporarily set to zero while the `ExtractIf` exists.
2025-11-20 11:15:50 +01:00
Seán de Búrca
5a8cf3362c alloc: Document panics when allocations will exceed max 2025-11-17 07:58:34 -08:00
Ralf Jung
fc07052f8b add must_use to extract_if methods 2025-11-16 15:57:23 +01:00
Stuart Cook
ec2f7397ce
Rollup merge of #148827 - GoldsteinE:stabilize-vec-into-raw-parts, r=Mark-Simulacrum
Stabilize vec_into_raw_parts

This stabilizes `Vec::into_raw_parts()` and `String::into_raw_parts()` per FCP in https://github.com/rust-lang/rust/issues/65816#issuecomment-3517630971. While this _does not_ stabilize `Vec::into_parts()`, I fixed up the examples that said they were waiting for `vec_into_raw_parts`. As `Vec::from_parts()` and `Vec::into_parts()` are covered by the same feature `box_vec_non_null`, any doctest that uses `Vec::from_parts()` can also use `Vec::into_parts()` (and same for allocator-aware versions).

Closes rust-lang/rust#65816

``@rustbot`` modify labels: +T-libs-api
2025-11-16 14:39:58 +11:00
Max Siling
ac9bb13267
Stabilize vec_into_raw_parts 2025-11-11 20:24:29 +03:00
Pavel Grigorenko
33da7285ac vec_recycle: implementation 2025-11-11 14:01:02 +03:00
bors
c8f22ca269 Auto merge of #148737 - zachs18:unit-is-zero, r=joboet
Implement IsZero for (), and optimize `IsZero::is_zero` for arrays

These are probably not super useful optimizations, but they make it so that `vec![expr; LARGE_LENGTH]` has better performance for some `expr`s, e.g.

* array of length zero in debug mode
* tuple containing `()` and zero-valued integers in debug and release mode
* array of `()` or other zero-sized `IsZero` type in debug mode

<details> <summary>very rough benchmarks</summary>

```Rust
use std::time::Instant;
use std::sync::atomic::{AtomicUsize, Ordering::Relaxed};

struct NonCopyZst;
static COUNTER: AtomicUsize = AtomicUsize::new(0);

impl Clone for NonCopyZst {
    fn clone(&self) -> Self {
        COUNTER.fetch_add(1, Relaxed);
        Self
    }
}

macro_rules! timeit {
    ($e:expr) => {
        let start = Instant::now();
        _ = $e;
        println!("{:56}: {:?}", stringify!($e), start.elapsed());
    };
}

fn main() {
    timeit!(vec![[String::from("hello"); 0]; 1_000_000_000]); // gets a lot better in debug mode
    timeit!(vec![(0u8, (), 0u16); 1_000_000_000]); // gets a lot better in debug *and* release mode
    timeit!(vec![[[(); 37]; 1_000_000_000]; 1_000_000_000]); // gets a lot better in debug mode
    timeit!(vec![[NonCopyZst; 0]; 1_000_000_000]); // gets a lot better in debug mode
    timeit!(vec![[[1u8; 0]; 1_000_000]; 1_000_000]); // gets a little bit better in debug mode
    timeit!(vec![[[(); 37]; 1_000_000]; 1_000_000]); // gets a little bit better in debug mode
    timeit!(vec![[[1u128; 0]; 1_000_000]; 1_000_000]); // gets a little bit better in debug mode

    // check that we don't regress existing optimizations
    timeit!(vec![(0u8, 0u16); 1_000_000_000]); // about the same time
    timeit!(vec![0u32; 1_000_000_000]); // about the same time

    // check that we still call clone for non-IsZero ZSTs
    timeit!(vec![[const { NonCopyZst }; 2]; 1_000]); // about the same time
    assert_eq!(COUNTER.load(Relaxed), 1998);
    timeit!(vec![NonCopyZst; 10_000]); // about the same time
    assert_eq!(COUNTER.load(Relaxed), 1998 + 9_999);
}

```

```rs
$ cargo +nightly run
// ...
vec![[String::from("hello"); 0]; 1_000_000_000]         : 11.13999724s
vec![(0u8, (), 0u16); 1_000_000_000]                    : 5.254646651s
vec![[[(); 37]; 1_000_000_000]; 1_000_000_000]          : 2.738062531s
vec![[NonCopyZst; 0]; 1_000_000_000]                    : 9.483690922s
vec![[[1u8; 0]; 1_000_000]; 1_000_000]                  : 2.919236ms
vec![[[(); 37]; 1_000_000]; 1_000_000]                  : 2.927755ms
vec![[[1u128; 0]; 1_000_000]; 1_000_000]                : 2.931486ms
vec![(0u8, 0u16); 1_000_000_000]                        : 19.46µs
vec![0u32; 1_000_000_000]                               : 9.34µs
vec![[const { NonCopyZst }; 2]; 1_000]                  : 31.88µs
vec![NonCopyZst; 10_000]                                : 36.519µs
```

```rs
$ cargo +dev run
// ...
vec![[String::from("hello"); 0]; 1_000_000_000]         : 4.12µs
vec![(0u8, (), 0u16); 1_000_000_000]                    : 16.299µs
vec![[[(); 37]; 1_000_000_000]; 1_000_000_000]          : 210ns
vec![[NonCopyZst; 0]; 1_000_000_000]                    : 210ns
vec![[[1u8; 0]; 1_000_000]; 1_000_000]                  : 170ns
vec![[[(); 37]; 1_000_000]; 1_000_000]                  : 110ns
vec![[[1u128; 0]; 1_000_000]; 1_000_000]                : 140ns
vec![(0u8, 0u16); 1_000_000_000]                        : 11.56µs
vec![0u32; 1_000_000_000]                               : 10.71µs
vec![[const { NonCopyZst }; 2]; 1_000]                  : 36.08µs
vec![NonCopyZst; 10_000]                                : 73.21µs
```

(checking release mode to make sure this doesn't regress perf there)

```rs
$ cargo +nightly run --release
// ...
vec![[String::from("hello"); 0]; 1_000_000_000]         : 70ns
vec![(0u8, (), 0u16); 1_000_000_000]                    : 1.269457501s
vec![[[(); 37]; 1_000_000_000]; 1_000_000_000]          : 10ns
vec![[NonCopyZst; 0]; 1_000_000_000]                    : 20ns
vec![[[1u8; 0]; 1_000_000]; 1_000_000]                  : 10ns
vec![[[(); 37]; 1_000_000]; 1_000_000]                  : 20ns
vec![[[1u128; 0]; 1_000_000]; 1_000_000]                : 20ns
vec![(0u8, 0u16); 1_000_000_000]                        : 20ns
vec![0u32; 1_000_000_000]                               : 20ns
vec![[const { NonCopyZst }; 2]; 1_000]                  : 2.66µs
vec![NonCopyZst; 10_000]                                : 13.39µs
```

```rs
$ cargo +dev run --release
vec![[String::from("hello"); 0]; 1_000_000_000]         : 90ns
vec![(0u8, (), 0u16); 1_000_000_000]                    : 30ns
vec![[[(); 37]; 1_000_000_000]; 1_000_000_000]          : 20ns
vec![[NonCopyZst; 0]; 1_000_000_000]                    : 30ns
vec![[[1u8; 0]; 1_000_000]; 1_000_000]                  : 20ns
vec![[[(); 37]; 1_000_000]; 1_000_000]                  : 20ns
vec![[[1u128; 0]; 1_000_000]; 1_000_000]                : 20ns
vec![(0u8, 0u16); 1_000_000_000]                        : 30ns
vec![0u32; 1_000_000_000]                               : 20ns
vec![[const { NonCopyZst }; 2]; 1_000]                  : 3.52µs
vec![NonCopyZst; 10_000]                                : 17.13µs
```
</details>

The specific expression I ran into a perf issue that this PR addresses is `vec![[(); LARGE]; LARGE]`, as I was trying to demonstrate `Vec::into_flattened` panicking on length overflow in the playground, but got a timeout error instead since `vec![[(); LARGE]; LARGE]` took so long to run in debug mode (it runs fine on the playground in release mode)
2025-11-11 02:44:37 +00:00
Zachary S
0aaa3ae47b Optimize Vec::from_elem for some more cases.
Implement IsZero for ().

Implement default `IsZero` for all arrays, only returning true if the array is empty
(making the existing array impl for `IsZero` elements a specialization).

Optimize `IsZero::is_zero` for arrays of zero-sized `IsZero` elements.
2025-11-09 11:28:42 -06:00
joboet
5fb5861765
(almost) get rid of the unsound #[rustc_unsafe_specialization_marker] on Copy, introduce TrivialClone 2025-11-09 15:51:25 +01:00
Waffle Lapkin
32c93ccc89
Merge Vec::push{,_mut}_within_capacity 2025-11-05 17:03:25 +01:00
Pavel Grigorenko
144707a4b1 Don't require T: RefUnwindSafe for vec::IntoIter<T>: UnwindSafe 2025-10-21 21:18:09 +03:00
bors
c7f6aa2869 Auto merge of #147042 - Noratrieb:untrack-caller-vec, r=tgross35
Remove most `#[track_caller]` from allocating Vec methods

They cause significant binary size overhead while contributing little value.

closes rust-lang/rust#146963, see that issue for more details.
2025-09-28 03:23:45 +00:00
Noratrieb
9316d4508c Remove most #[track_caller] from allocating Vec methods
They cause significant binary size overhead while contributing little
value.

Also removes them from the wrapping String methods that do not panic.
2025-09-25 20:52:03 +02:00
Matthias Krüger
fea9196e52
Rollup merge of #146293 - BenjaminBrienen:try_remove, r=joboet
feat: non-panicking `Vec::try_remove`

`if index < my_vector.len() { Some(my_vector.remove(index)) } else { None }` is annoying to write and non-panicking functions are broadly useful.

APC: https://github.com/rust-lang/libs-team/issues/649

Tracking issue: https://github.com/rust-lang/rust/issues/146954
2025-09-25 18:15:09 +02:00
Matthias Krüger
e3f7626732
Rollup merge of #141032 - petrosagg:extract-if-ub, r=joboet
avoid violating `slice::from_raw_parts` safety contract in `Vec::extract_if`

The implementation of the `Vec::extract_if` iterator violates the safety contract adverized by `slice::from_raw_parts` by always constructing a mutable slice for the entire length of the vector even though that span of memory can contain holes from items already drained. The safety contract of `slice::from_raw_parts` requires that all elements must be properly
initialized.

As an example we can look at the following code:

```rust
let mut v = vec![Box::new(0u64), Box::new(1u64)];
for item in v.extract_if(.., |x| **x == 0) {
    drop(item);
}
```

In the second iteration a `&mut [Box<u64>]` slice of length 2 will be constructed. The first slot of the slice contains the bitpattern of an already deallocated box, which is invalid.

This fixes the issue by only creating references to valid items and using pointer manipulation for the rest. I have also taken the liberty to remove the big `unsafe` blocks in place of targetted ones with a SAFETY comment. The approach closely mirrors the implementation of `Vec::retain_mut`.

**Note to reviewers:** The diff is easier to follow with whitespace hidden.
2025-09-25 18:15:07 +02:00
joboet
09097128c3
alloc: fix Debug implementation of ExtractIf 2025-09-25 17:48:08 +02:00
BenjaminBrienen
56734495e2 feature: Implement vec_try_remove
Vec::try_remove is a non-panicking version of Vec::remove
2025-09-24 15:29:09 +02:00
Petros Angelatos
e9b2c4f395 avoid violating slice::from_raw_parts safety contract in Vec::extract_if
The implementation of the `Vec::extract_if` iterator violates the safety
contract adverized by `slice::from_raw_parts` by always constructing a
mutable slice for the entire length of the vector even though that span
of memory can contain holes from items already drained. The safety
contract of `slice::from_raw_parts` requires that all elements must be
properly initialized.

As an example we can look at the following code:

```rust
let mut v = vec![Box::new(0u64), Box::new(1u64)];
for item in v.extract_if(.., |x| **x == 0) {
    drop(item);
}
```

In the second iteration a `&mut [Box<u64>]` slice of length 2 will be
constructed. The first slot of the slice contains the bitpattern of an
already deallocated box, which is invalid.

This fixes the issue by only creating references to valid items and
using pointer manipulation for the rest. I have also taken the liberty
to remove the big `unsafe` blocks in place of targetted ones with a
SAFETY comment. The approach closely mirrors the implementation of
`Vec::retain_mut`.

Signed-off-by: Petros Angelatos <petrosagg@gmail.com>
2025-09-22 10:59:52 +03:00
Ben Kimock
df58fd8cf7 Change the cfg to a dash 2025-09-21 13:12:20 -04:00
Ben Kimock
888679013d Add panic=immediate-abort 2025-09-21 13:12:18 -04:00
tk
ac3c480388 docs: improve doc of some methods w/ ranges 2025-09-20 10:17:56 +00:00
Sidney Cammeresi
934ee043fe
Plumb Allocator generic into std::vec::PeekMut 2025-09-18 17:29:23 -07:00
Sidney Cammeresi
ce859d7713
Switch std::vec::PeekMut::pop from self to this parameter.
Since PeekMut implements Deref, it shouldn't have any methods of its
own.

See also: `std::collections::binary_heap::PeekMut::pop`
2025-09-14 08:16:05 -07:00
ltdk
d6945f6d8c Add cast_init and cast_uninit methods for pointers 2025-08-12 16:57:56 -04:00
SabrinaJewson
1ce4b370e4
Handle the capacity == 0 case 2025-08-12 05:12:34 +01:00