From: René Scharfe Date: Sun, 18 Jan 2026 14:58:27 GMT Subject: Re: [PATCH 01/10] ivec: introduce the C side of ivec Message-ID: In-Reply-To: On 1/17/26 5:04 PM, Ezekiel Newren wrote: > > I don't like this solution. ivec_push() is the only function that > deals with actual values. The rest are just generic memory management > functions. What if we used: > > #define ivec_init(vec) { \ > (vec)->ptr = NULL; \ > (vec)->length = 0; \ > (vec)->capacity = 0; \ > (vec)->element_size = sizeof(*(vec)->ptr); \ > } > > #define ivec_push_unsafe(vec, value) (vec)->ptr[(vec)->length++] = (value) > > /* > * grow by at least 1 > */ > #define ivec_push(vec, value) { \ > if ((vec)->length == (vec)->capacity) \ > ivec_reserve(vec, 1); \ > ivec_push_unsafe(vec, value); \ > } > > Instead of concrete functions? These macros are OK on the C side in respect to type-safety. I guess they would have to be duplicated somehow in Rust? How would ivec_reserve() look like? The macros use their parameter "vec" multiple times, though, so callers must not pass in an expression with a side-effect, as it would be evaluated more than once. We have a few of those already. You have to be careful not to do stuff like this (example of calling a _push-like function with an argument with a side-effect from strbuf.c::strbuf_join_argv()): while (--argc) strbuf_addstr(buf, *(++argv)); Also they can't be used like a function -- you'd have to call them without a trailing semicolon. That's a small issue and easily overcome by wrapping their body in "do { } while (0)". René