Skip to content

RFC: Vec::recycle #2802

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

Closed
wants to merge 8 commits into from
Closed
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions text/0000-recycle-vec.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ impl Vec<T> {
assert_eq!(core::mem::size_of::<T>(), core::mem::size_of::<U>());
assert_eq!(core::mem::align_of::<T>(), core::mem::align_of::<U>());
self.clear();
let (ptr, len, capacity) = self.into_raw_parts();
let (ptr, _, capacity) = self.into_raw_parts();
let ptr = ptr as *mut U;
unsafe { Vec::from_raw_parts(ptr, 0, capacity) }
}
Expand Down Expand Up @@ -205,6 +205,13 @@ directly subtyping relations between two generic types in where clauses. [1]
Thus, it was deemed to be sufficient to limit verification of the memory layout to the checking
of size and alignment of the stored type.

There is an alternative to this API, provided by https://crates.io/crates/vec_utils,
that instead of panicking on mismatching size or alignment, just allocates a new `Vec`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vec-utils does not allocate a new Vec, it just returns Vec::new() if the layouts are incompatible

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, indeed, Vec::new() doesn't allocate.

and returns it. This has the advantage that it works well in generic contexts.
The API proposed here takes stricter stance against allocating, not allowing
allocating by mistake. On the other hand, it's harder to use in generic contexts.
There might be room for providing both kind of APIs.

The impact of not doing is this is that those who need to reuse allocations and run into
lifetime problems as described in the Guide-level explanation, either
1. use a crate such as https://crates.io/crates/recycle_vec
Expand All @@ -226,7 +233,16 @@ https://www.reddit.com/r/rust/comments/dmvsm0/a_question_about_where_clauses_and
# Prior art
[prior-art]: #prior-art

The same API is provided by the crate `recycle_vec` via an extension trait on `Vec`: https://crates.io/crates/recycle_vec
A prior implementation of a similar API is provided by the crate `vec-utils`:
https://crates.io/crates/vec_utils

The same API as here is also provided by the crate `recycle_vec`, intended to test the implementation:
https://crates.io/crates/recycle_vec

There is also an unmerged RFC about transmuting `Vec`s: https://github.com/rust-lang/rfcs/pull/2756
The difference with this RFC is that this RFC intends to provide a safe
API for reusing the allocation and doesn't concern itself with transmuting/reinterpreting the
content values of `Vec`.

The author is unaware about prior art outside of the Rust language and its ecosystem;
it might be hard to find as the proposed API is positioned in the cutting point of high performance processing,
Expand All @@ -248,6 +264,9 @@ Should we add this API to other, or possibly all collections in the standard lib
or the stabilization must be delayed until compile-time asserts are available.
- It seems that there are currently no plans about supporting generic type parameters in const context. This means that
asserting a size of a type as a compile time assertion seems to be like a far-fetched feature.
- The API provided by this RFC panics on size or alignment mismatch. An alternative to this is to consider the allocation just an
optional optimization, and silently allocate a new, compatible `Vec` in case the old allocation can't be reused. It's also
plausible that both kind of APIs are provided.
- Anything else?

# Future possibilities
Expand Down