-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tracking Issue for Vec::push_within_capacity #100486
Comments
Would it be possible for |
It still needs to bump the length field. |
Wouldn't wrapping the length in |
Ah wait I think I see the issue. You'd lose |
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. |
Hi! I think this could enter its FCP:
|
I find it very useful, and have similar helpers in my codebases. It generates much leaner code than the usual However, just |
I hope this isn't completely useful, |
How about |
Sounds interesting, though a bit niche (just like this method). If you have a use-case you should file an ACP for it. 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. |
Now that it's possible to do a try_reserve, I find myself using these extension methods a lot more often. // ===== trait Ext =====
pub trait Ext<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()`.
///
unsafe fn unchecked_push(&mut self, 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`.
///
unsafe fn unchecked_pop(&mut self) -> 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()`
///
unsafe fn unchecked_insert(&mut self, 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.
///
fn insert_within_capacity(&mut self, 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
///
fn try_insert_within_capacity(&mut self, index: usize, element: T) -> Result<(), T>;
}
// ===== impl Vec =====
impl<T> Ext<T> for Vec<T> {
unsafe fn unchecked_push(&mut self, value: T) {
std::hint::assert_unchecked(self.len() < self.capacity());
self.push_within_capacity(value).unwrap_unchecked();
}
unsafe fn unchecked_pop(&mut self) -> T {
std::hint::assert_unchecked(!self.is_empty());
self.pop().unwrap_unchecked()
}
unsafe fn unchecked_insert(&mut self, index: usize, element: T) {
std::hint::assert_unchecked(index <= self.len());
std::hint::assert_unchecked(self.len() < self.capacity());
self.insert(index, element);
}
fn insert_within_capacity(&mut self, index: usize, element: T) -> Result<(), T> {
if self.len() == self.capacity() {
return Err(element);
}
unsafe { std::hint::assert_unchecked(self.len() < self.capacity()) };
self.insert(index, element);
Ok(())
}
fn try_insert_within_capacity(&mut self, index: usize, element: T) -> Result<(), T> {
if self.len() == self.capacity() || index > self.len() {
return Err(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:
|
This |
Although it's somewhat similar,
|
I assume that was only intended to point at some similar-not-identical prior art, not suggesting that BorrowedBuf can be reused for the purpose.
Yeah, imo this is the biggest obstacle to getting anything done. It's either a lot new awkwardly named methods, view types or some generics/associated type shenanigans. Thinking about design I now realize that there's an alternative, it could take a |
How about something like this:
it makes it easy to solve both problems... the trick is that the implementation must match exactly to what RawVec does, otherwise the optimizer doesn't realize that the operations are identical. |
I don't think it's important to return elements that couldn't fit in the capacity. This isn't like I/O functions or concurrent queues where you can't predict whether insert will succeed or not. When you want to keep the elements that can't be inserted, it's sufficient to check the capacity before push/extend. |
The main problem is the that obvious |
Returning the value that couldn’t be pushed/inserted/etc. only seems to matter if:
I struggle to imagine a use case with these properties that isn’t isomorphic to “generic I guess if you use a Vec as a fixed size buffer of non-Copy elements and want to flush the buffer to another stage of processing whenever it gets full? This needs If any use case for more than |
Feature gate:
#![feature(vec_push_within_capacity)]
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.Public API
Steps / History
Unresolved Questions
push_in_capacity
)Footnotes
https://std-dev-guide.rust-lang.org/feature-lifecycle/stabilization.html ↩
The text was updated successfully, but these errors were encountered: