The following code results in i being 2. I think it might be a bug in Zig, but it’s sufficiently confusing that I’m not sure. Is this expected behavior? What’s going on?
fn nop() error{E}!void {}
pub fn main() !void {
comptime var i = 0;
{
defer {
i += 1;
}
try nop();
}
@compileLog(i); // outputs 2
}
To elaborate on this.
In addition to the natural end of the block, try introduces another exit to propagate the error from nop. defer places its statement at both exits as is expected and because i is a comptime var both get evaluated at compile time, hence i being 2.
If the nop returns an empty error set, then zig knows there is no error to propagate so try doesn’t introduce another exit, hence i being 1.
Well, what’s confuses me about this explanation is that the following code, which I think should be identical, instead outright fails to compile (even without the compileLog statement):
fn nop() error{E}!void {}
pub fn main() !void {
comptime var i = 0;
{
defer {
i += 1;
}
nop() catch |e| return e;
}
@compileLog(i); // this statement is never reached
}
It fails with:
src/main.zig:7:15: error: store to comptime variable depends on runtime condition
i += 1;
~~^~~~
src/main.zig:9:15: note: runtime condition here
nop() catch |e| return e;
~~~~~~^~~~~~~~~~~~~~~~~~