Hi,
I hit a runtime panic with a tagged union and want to confirm whether this is expected based on Zig’s evaluation rules.
Given:
const State = union(enum) {
alive: Alive,
exploding: Exploding,
};
And:
if (bullet.state != .alive) return;
bullet.state = .{
.exploding = .{
.origin = bullet.state.alive.body.pos(),
},
};
This panics at runtime:
panic: access of union field 'alive' while field 'exploding' is active
Logging shows bullet.state is alive at function entry. There is no threading and nothing else mutates bullet.state in between.
However, this works:
const exploding = Exploding{
.origin = bullet.state.alive.body.pos(),
};
bullet.state = .{ .exploding = exploding };
It seems that Zig does not guarantee evaluation order here, and that during the first form the union tag may be updated as part of the assignment before the nested bullet.state.alive expression is evaluated.
Is that the correct interpretation?
More generally:
- Does Zig guarantee that the RHS of an assignment is fully evaluated before the LHS is mutated?
- Is it considered undefined / unspecified to read from
xin the same expression wherexis assigned a different union tag? - Are there any other related gotchas to be aware of?
Thanks.