-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Vec::recycle (experimental API implementation) #66069
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
Changes from 2 commits
7e78e61
6ebdc5d
2d214d5
161cab2
8e246b4
e7ffde2
35e4d9b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -603,6 +603,92 @@ impl<T> Vec<T> { | |
self.buf.try_reserve_exact(self.len, additional) | ||
} | ||
|
||
/// Allows re-interpreting the type of a Vec to reuse the allocation. | ||
golddranks marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// The vector is emptied and any values contained in it will be dropped. | ||
golddranks marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// The target type must have the same size and alignment as the source type. | ||
/// This API doesn't transmute any values of T to U, because it makes sure | ||
golddranks marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// to empty the vector before any unsafe operations. | ||
/// | ||
/// # Example | ||
/// | ||
/// This API is useful especially when using `Vec` as a | ||
/// temporary storage for data with short lifetimes. | ||
/// By recycling the allocation, the `Vec` is able to safely | ||
/// outlive the lifetime of the type that was stored in it. | ||
/// ``` | ||
/// # #![feature(recycle_vec)] | ||
golddranks marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// # use std::error::Error; | ||
/// # | ||
/// # struct Stream(bool); | ||
/// # | ||
/// # impl Stream { | ||
/// # fn new() -> Self { | ||
/// # Stream(false) | ||
/// # } | ||
/// # | ||
/// # fn next(&mut self) -> Option<&[u8]> { | ||
/// # if self.0 { | ||
/// # None | ||
/// # } else { | ||
/// # self.0 = true; | ||
/// # Some(&b"foo"[..]) | ||
/// # } | ||
/// # } | ||
/// # } | ||
/// # | ||
/// # fn process(input: &[Object<'_>]) -> Result<(), Box<dyn Error>> { | ||
/// # for obj in input { | ||
/// # let _ = obj.reference; | ||
/// # } | ||
/// # Ok(()) | ||
/// # } | ||
/// # | ||
/// # struct Object<'a> { | ||
/// # reference: &'a [u8], | ||
/// # } | ||
/// # | ||
/// # fn deserialize<'a>(input: &'a [u8], output: &mut Vec<Object<'a>>) -> Result<(), Box<dyn Error>> { | ||
/// # output.push(Object { reference: input }); | ||
/// # Ok(()) | ||
/// # } | ||
/// # | ||
/// # fn main() -> Result<(), Box<dyn Error>> { | ||
/// # let mut stream = Stream::new(); | ||
/// let mut objects: Vec<Object<'static>> = Vec::new(); // Any lifetime goes here | ||
/// | ||
/// while let Some(byte_chunk) = stream.next() { // `byte_chunk` lifetime starts | ||
/// let mut temp: Vec<Object<'_>> = objects.recycle(); // `temp` lifetime starts | ||
/// | ||
/// // Zero-copy parsing; deserialized `Object`s have references to `byte_chunk` | ||
golddranks marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// deserialize(byte_chunk, &mut temp)?; | ||
/// process(&temp)?; | ||
/// | ||
/// objects = temp.recycle(); // `temp` lifetime ends | ||
/// } // `byte_chunk` lifetime ends | ||
/// # Ok(()) | ||
/// # } | ||
/// ``` | ||
/// | ||
/// # Panics | ||
/// Panics if the size or alignment of the source and target types don't match. | ||
golddranks marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// | ||
/// # Note about stabilization | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be removed now? |
||
/// The size and alignment contract is enforceable at compile-time, | ||
/// so we will want to wait until compile-time asserts become stable and | ||
/// modify this API to cause a compile error instead of panicking | ||
/// before stabilizing it. | ||
#[unstable(feature = "recycle_vec", reason = "new API", issue = "0")] | ||
pub fn recycle<U>(mut self) -> Vec<U> { | ||
self.truncate(0); | ||
// TODO make these const asserts once it becomes possible | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there an actual plan for making this possible? Even with compile time assertions, you wouldn't actually be able to reference There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is a question that needs to be resolved. It is mentioned as an unresolved question in the RFC. The problem is that changing to compile-time error is a breaking change, so whatever gets decided, we must commit to before stabilizing. I assumed that once the const functions support conditionals, creating compile time assertion for this case would be possible, but I had a hidden assumption that if there is a generic const function, I could pass it generic types that are in scope. Is the latter not the case? I wonder if there are explicit plans about supporting or not supporting that, or is it just more about how it currently is? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's not the case and there are no current plans to change that so don't expect it to change within the next 1.5 years at least. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All right, I removed the |
||
assert_eq!(core::mem::size_of::<T>(), core::mem::size_of::<U>()); | ||
assert_eq!(core::mem::align_of::<T>(), core::mem::align_of::<U>()); | ||
let capacity = self.capacity(); | ||
golddranks marked this conversation as resolved.
Show resolved
Hide resolved
|
||
let ptr = self.as_mut_ptr() as *mut U; | ||
core::mem::forget(self); | ||
unsafe { Vec::from_raw_parts(ptr, 0, capacity) } | ||
} | ||
|
||
/// Shrinks the capacity of the vector as much as possible. | ||
/// | ||
/// It will drop down as close as possible to the length but the allocator | ||
|
Uh oh!
There was an error while loading. Please reload this page.