You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Tracking Issue for Vec::push_within_capacity #100486
This is a tracking issue for Vec::push_within_capacity
It enables pushing into a Vec if there is any capacity left and otherwise returns the value. I.e. it avoids implicit resizing. This can be useful when one wants to explicitly control it (e.g. via try_reserve) or uses a Vec in an unsafe manner where moving the elements would be a problem.
Would it be possible for push_within_capacity to take self by shared reference? If the backing store is never re-allocated then calling this wouldn't invalidate any references to the Vec's contents, I'd think.
I think this is a great feature. I often find myself just assuming my buffer reserving code is working since it is a hard bug to catch when it's not working given push automatically reserves.
I find it very useful, and have similar helpers in my codebases. It generates much leaner code than the usual push when the optimizer can't be convinced that the capacity is sufficient (e.g. when it's calculated in a non-trivial way, or the vec-appending code isn't all inlined). It has a useful side effect of verifying that a sufficient capacity has been precalculated, and there aren't unexpected reallocations.
However, just push is not enough. I'm missing similar functionality for extend_from_slice — _within_capacity.
I hope this isn't completely useful,
But is there some kind of mechanism we can use to allow all these try_ functionality without adding dozens of try_ in all collections, could being generic over the effect of try allow something like this?
Now that it's possible to do a try_reserve, I find myself using these extension methods a lot more often. push_within_capacity here gives us an escape hatch to do an unchecked_push.
I included an example of insert_within_capacity and try_insert_within_capacity
// ===== trait Ext =====pubtraitExt<T>{/// Appends an element to the back of a collection without checking/// if the collection has enough capacity.////// # Safety/// The user must ensure that `self.len() < self.capacity()`.///unsafefnunchecked_push(&mutself,value:T);/// Removes the last element from a vector without checking/// if the collection is empty.////// # Safety/// The user must ensure that `self.len() != 0`.///unsafefnunchecked_pop(&mutself) -> T;/// Inserts an element at position index within the vector, /// without checking if the collection has enough capacity, /// or the position index is out of bounds./// all elements after the position index are shifted to the right. /// /// # Safety/// The user must ensure that `index <= self.len()` and `self.len() < self.capacity()`///unsafefnunchecked_insert(&mutself,index:usize,value:T);/// Inserts an element at position index within the vector, /// if there is sufficient spare capacity, otherwise an error is returned with the element./// /// # Errors/// if insufficient capacity, an error is returned with the element/// /// # Panics/// Panics if index > len./// fninsert_within_capacity(&mutself,index:usize,element:T) -> Result<(),T>;/// Inserts an element at position index within the vector, /// if there is sufficient spare capacity, and index is within bounds,/// otherwise an error is returned with the element./// /// # Errors/// if insufficient capacity, or the index is out of bounds, an error is returned with the element/// fntry_insert_within_capacity(&mutself,index:usize,element:T) -> Result<(),T>;}// ===== impl Vec =====impl<T>Ext<T>forVec<T>{unsafefnunchecked_push(&mutself,value:T){
std::hint::assert_unchecked(self.len() < self.capacity());self.push_within_capacity(value).unwrap_unchecked();}unsafefnunchecked_pop(&mutself) -> T{
std::hint::assert_unchecked(!self.is_empty());self.pop().unwrap_unchecked()}unsafefnunchecked_insert(&mutself,index:usize,element:T){
std::hint::assert_unchecked(index <= self.len());
std::hint::assert_unchecked(self.len() < self.capacity());self.insert(index, element);}fninsert_within_capacity(&mutself,index:usize,element:T) -> Result<(),T>{ifself.len() == self.capacity(){returnErr(element);}unsafe{ std::hint::assert_unchecked(self.len() < self.capacity())};self.insert(index, element);Ok(())}fntry_insert_within_capacity(&mutself,index:usize,element:T) -> Result<(),T>{ifself.len() == self.capacity() || index > self.len(){returnErr(element);}unsafe{self.unchecked_insert(index, element);}Ok(())}}
There are two ways to implement such functionality, and I'm not sure which way to propose:
Add more methods on Vec with a _within_capacity version. I think this would work well, but I've got a lot of pushback about adding try_ versions of methods. Rust doesn't have a feature like Swift's function naming/overloading to keep all of these functionality tweaks elegantly together.
A reference type like FixedCapacityVecView<'_> that imitates interface of Vec, but without reallocation. This seems like a big addition, especially if it will duplicate most of Vec's interface, but most users will probably only need push and extend.
Activity
em-tg commentedon Mar 19, 2023
Would it be possible for
push_within_capacityto takeselfby shared reference? If the backing store is never re-allocated then calling this wouldn't invalidate any references to theVec's contents, I'd think.the8472 commentedon Mar 19, 2023
It still needs to bump the length field.
em-tg commentedon Mar 19, 2023
Wouldn't wrapping the length in
UnsafeCellwork for that? The public api only exposes thelen()getter.em-tg commentedon Mar 20, 2023
Ah wait I think I see the issue. You'd lose
Syncby doing that. Sorry, still pretty new to Rust and just thought I'd ask!tiby312 commentedon Jun 19, 2023
I think this is a great feature. I often find myself just assuming my buffer reserving code is working since it is a hard bug to catch when it's not working given push automatically reserves.
krtab commentedon Oct 27, 2023
Hi!
I think this could enter its FCP:
Errreturn value as unreachablekornelski commentedon Feb 11, 2024
I find it very useful, and have similar helpers in my codebases. It generates much leaner code than the usual
pushwhen the optimizer can't be convinced that the capacity is sufficient (e.g. when it's calculated in a non-trivial way, or the vec-appending code isn't all inlined). It has a useful side effect of verifying that a sufficient capacity has been precalculated, and there aren't unexpected reallocations.However, just
pushis not enough. I'm missing similar functionality forextend_from_slice—_within_capacity.elichai commentedon Feb 11, 2024
I hope this isn't completely useful,
But is there some kind of mechanism we can use to allow all these
try_functionality without adding dozens oftry_in all collections, could being generic over the effect oftryallow something like this?Darksonn commentedon May 1, 2024
How about
insert_within_capacity? It's very non-trivial to reimplementinsertwithout an allocation codepath.the8472 commentedon May 1, 2024
Sounds interesting, though a bit niche (just like this method). If you have a use-case you should file an ACP for it.
Ditto @kornelski
If you several a bunch of methods like this in mind then we could perhaps bundle them to see if there are some overarching things to consider.
zeroflaw commentedon May 9, 2024
Now that it's possible to do a try_reserve, I find myself using these extension methods a lot more often.
push_within_capacityhere gives us an escape hatch to do anunchecked_push.I included an example of
insert_within_capacityandtry_insert_within_capacitykornelski commentedon May 9, 2024
There are two ways to implement such functionality, and I'm not sure which way to propose:
Add more methods on
Vecwith a_within_capacityversion. I think this would work well, but I've got a lot of pushback about addingtry_versions of methods. Rust doesn't have a feature like Swift's function naming/overloading to keep all of these functionality tweaks elegantly together.A reference type like
FixedCapacityVecView<'_>that imitates interface ofVec, but without reallocation. This seems like a big addition, especially if it will duplicate most of Vec's interface, but most users will probably only needpushandextend.GoldsteinE commentedon Jun 5, 2024
This
FixedCapacityVecView<'_>is kinda similar tostd::io::BorrowedBuf<'_>in both its API and idea.11 remaining items
Rollup merge of rust-lang#148534 - WaffleLapkin:push_within_capacity_…
Rollup merge of rust-lang#148534 - WaffleLapkin:push_within_capacity_…
Unrolled build for #148534
Rollup merge of #148534 - WaffleLapkin:push_within_capacity_now_with_…
Rollup merge of #148534 - WaffleLapkin:push_within_capacity_now_with_…
Rollup merge of rust-lang#148534 - WaffleLapkin:push_within_capacity_…
Rollup merge of rust-lang#148534 - WaffleLapkin:push_within_capacity_…
WaffleLapkin commentedon Nov 13, 2025
#148534 changed the signature to return a reference to the pushed element, just like
push_mut& co.Rollup merge of #148534 - WaffleLapkin:push_within_capacity_now_with_…
Rollup merge of rust-lang#148534 - WaffleLapkin:push_within_capacity_…
Rollup merge of #148534 - WaffleLapkin:push_within_capacity_now_with_…
Rollup merge of #148534 - WaffleLapkin:push_within_capacity_now_with_…
Rollup merge of #148534 - WaffleLapkin:push_within_capacity_now_with_…