Subject: Re: [PATCH 01/10] ivec: introduce the C side of ivec

From: René Scharfe <[email-masked]>
Date: Sun, 18 Jan 2026 15:58:27 +0100

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é