Zig Version
0.10.0-dev.2880+6f0807f50
Steps to Reproduce
const std = @import("std");
const X = struct {
a: u16,
b: u16,
};
test {
var x = X {
.a = 47,
.b = 234,
};
// swap x.a and x.b
x = .{
.a = x.b,
.b = x.a,
};
try std.testing.expectEqual(@as(u16, 234), x.a);
try std.testing.expectEqual(@as(u16, 47), x.b);
}
Expected Behavior
Conceptually, I expect everything on the right side of an assignment to be evaluated before the left side is modified.
So x.a should be 234 and x.b should be 47, and the test should pass.
Actual Behavior
Both x.a and x.b ends up being equal to 234, and the test fails:
Test [1/1] test ""... expected 47, found 234
Test [1/1] test ""... FAIL (TestExpectedEqual)
C:\...\zig\lib\std\testing.zig:79:17: 0x7ff607721fc8 in td.testing.expectEqual (test.obj)
return error.TestExpectedEqual;
^
C:\...\swap.zig:21:5: 0x7ff60772176a in est "" (test.obj)
try std.testing.expectEqual(@as(u16, 47), x.b);
^
0 passed; 0 skipped; 1 failed.
It would appear that the compiler has transformed the swap into the equivalent of:
The documentation doesn't say much about order of evaluation guarantees as far as I can tell, so maybe this is just undefined behavior in zig, but if that's the case, it seems like a pretty big footgun.
Zig Version
0.10.0-dev.2880+6f0807f50
Steps to Reproduce
Expected Behavior
Conceptually, I expect everything on the right side of an assignment to be evaluated before the left side is modified.
So
x.ashould be 234 andx.bshould be 47, and the test should pass.Actual Behavior
Both
x.aandx.bends up being equal to 234, and the test fails:It would appear that the compiler has transformed the swap into the equivalent of:
The documentation doesn't say much about order of evaluation guarantees as far as I can tell, so maybe this is just undefined behavior in zig, but if that's the case, it seems like a pretty big footgun.