Skip to content

Conversation

russelltg
Copy link
Contributor

@russelltg russelltg commented Jan 4, 2024

Efficient insertions into CxxVector requires reserving additional capacity. This also adds a way to query current capacity.

Also implement extend, which can use the size hint

begin_function_definition(out);
writeln!(
out,
"void cxxbridge1$std$vector${}$reserve(::std::vector<{}> *s, ::std::size_t new_cap) {{",
Copy link
Owner

Choose a reason for hiding this comment

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

Whether or not the underlying C++ API can throw an exception, this needs a noexcept to block a C++ exception from unwinding across an FFI boundary which is UB.

Suggested change
"void cxxbridge1$std$vector${}$reserve(::std::vector<{}> *s, ::std::size_t new_cap) {{",
"void cxxbridge1$std$vector${}$reserve(::std::vector<{}> *s, ::std::size_t new_cap) noexcept {{",

}
}

impl<A> Extend<A> for Pin<&mut CxxVector<A>>
Copy link
Owner

Choose a reason for hiding this comment

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

It is almost always more appropriate to match the type definition's generic parameter names than the trait definition's.

Suggested change
impl<A> Extend<A> for Pin<&mut CxxVector<A>>
impl<T> Extend<T> for Pin<&mut CxxVector<T>>

unsafe fn __get_unchecked(v: *mut CxxVector<$ty>, pos: usize) -> *mut $ty {
extern "C" {
#[link_name = concat!("cxxbridge1$std$vector$", $segment, "$get_unchecked")]
fn __get_unchecked(_: *mut CxxVector<$ty>, _: usize) -> *mut $ty;
}
unsafe { __get_unchecked(v, pos) }
}
unsafe fn __reserve(v: Pin<&mut CxxVector<$ty>>, pos: usize) {
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
unsafe fn __reserve(v: Pin<&mut CxxVector<$ty>>, pos: usize) {
unsafe fn __reserve(v: Pin<&mut CxxVector<$ty>>, new_cap: usize) {

unsafe fn __get_unchecked(v: *mut CxxVector<Self>, pos: usize) -> *mut Self;
#[doc(hidden)]
unsafe fn __reserve(v: Pin<&mut CxxVector<Self>>, new_capacity: usize);
Copy link
Owner

Choose a reason for hiding this comment

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

This is called new_cap everywhere else.

Suggested change
unsafe fn __reserve(v: Pin<&mut CxxVector<Self>>, new_capacity: usize);
unsafe fn __reserve(v: Pin<&mut CxxVector<Self>>, new_cap: usize);

pub fn reserve(self: Pin<&mut Self>, additional: usize) {
unsafe {
let len = self.as_ref().len();
T::__reserve(self, len + additional);
Copy link
Owner

Choose a reason for hiding this comment

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

This is unsound without checked addition. As written, something like vector.reserve(usize::MAX) will silently do nothing in release mode where arithmetic overflow checks are off and the addition wraps.

Copy link
Owner

@dtolnay dtolnay left a comment

Choose a reason for hiding this comment

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

Thanks!

@dtolnay dtolnay merged commit 3ee095c into dtolnay:master Aug 10, 2025
@dtolnay dtolnay mentioned this pull request Aug 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants