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