var foo = Wrapper{ .i = 1 };
var bar = Wrapper{ .i = 2 };
foo.add(bar);
The compiler is smart enough to essentially rewrite foo.add(...) as Wrapper.add(&foo, ...) for you. If you’re trying to use the mutable pointer to the struct held by foo in another context, just say &foo manually.
The stage2 issue might be a bug, but you don’t need to take its pointer at the call site explicitly.
This is not really control flow, it’s just value passing semantics:
when you receive a Wrapper as a function argument, modifications to that object will not be visible outside the function and Zig may pass it by copy
when you receive a *Wrapper, modifications to that object will be visible outside the function, and Zig will not copy the value
when you receive a *const Wrapper, modifications to that object are not possible, and Zig will not copy the value
Does that make sense? If your local variable foo is mutable and the function call receives a non-const pointer to it, you can use it without any decoration and Zig will do the rest.