Re: [PATCH v3 06/15] ivec: create a vector type that is interoperable between C and Rust
- From
Ezekiel Newren <ezekielnewren@gmail.com>
- Date
- Aug 26, 2025, 18:47 UTC
- Message-ID
- <CAH=ZcbD_pX1YdZbt9b-xMmcu2806twhjECez4HhCyE9iBf-9=Q@mail.gmail.com>
- In-Reply-To
- <CALnO6CASgMQ=cbQ_ijWXV0RMMSZgvS47r8ucTro7Wc4pgZ9_jQ@mail.gmail.com>
On Tue, Aug 26, 2025 at 7:30 AM D. Ben Knoble <ben.knoble@gmail.com> wrote:
Show 13 quoted lines
> > > Am I reading the patch correctly that the ivec implementation is primarily C? I’m not familiar with too many FFI projects in Rust, but I might have hoped we could write parts in Rust to gain any benefits from that, too. Is that a fool’s errand I’m thinking of? > > > > The ivec type is defined and implemented in C (interop/ivec.[ch]) and > > Rust (rust/interop/src/ivec.rs). When I started writing the ivec type > > I didn't know if the Git community would accept a hard dependency on > > Rust, so I made ivec usable in C without needing Rust. > > Right—I saw both implementations, but it looked like C did most of the > work, which was my main question. Re-reading, it looks like Rust does > more work than I thought (with implementations of insert/push/etc.) > > That said, I think it's sensible to leave the type useable from just C > unless/until Rust becomes required (and then we can move things over).
I like your idea of implementation consolidation. I just don't know what that would look like yet.
It's not straightforward because C doesn't have generics. I'll use IVec as an example, but this applies to any generic type in Rust. For a function like push() in IVec<T> it will have N definitions if there are N IVec types. e.g. If your code uses IVec<u64>, IVec<u8>, IVec<i32> that would mean that pub fn push(&mut self) {} would compile to 3 functions. If you don't use #[no_mangle] you'd have to figure out the Rust compiler's exact behavior for function names when calling it from C, which isn't stable or easily predictable. If you do use #[no_mangle] then the Rust compiler can't generate a generic function for each type.
Another problem is that the functions in ivec mostly deal with resizing the memory rather than controlling access to memory for the C side. Even if the C side used Rust defined functions, that wouldn't solve memory access issues to the pointer on the C side. We could enforce access to each element by requiring C to call a Rust defined function for each element, but that sounds very painful and slow. ivec is meant to be used as a scaffolding type to help transition C to Rust.
Other projects that do use Rust's builtin Vec (or some other collection type) often Box it and write wrapper functions. This means that the C side sees an opaque void* instead of a transparent struct like ivec with ptr, length, capacity, and element_size.
I'm curious if the community has more design feedback, or suggestions for an alternative to my ivec type.