3 ms·
Actually arithmetic is even less defined in Zig than in C! For example, addition with unsigned integers in C is well-defined, but it is (safety-protected) undef
by AndyKelley 8y ago
Actually arithmetic is even less defined in Zig than in C! For example, addition with unsigned integers in C is well-defined, but it is (safety-protected) undefined behavior in Zig.
I actually agree with you that the most obvious way should emphasize correctness over speed, and that's why +, -, /, and * operators have language-level assertions to protect against integer overflow - which is almost always a bug.
If Muon only has well-defined arithmetic, then it would not be able to catch this bug:
const std = @import("std");
test "contrived example" {
const income = 1000;
const taxes = 1009;
const cost_of_living = 300;
std.testing.expect(!isValidSalary(income, taxes, cost_of_living));
}
fn isValidSalary(income: u32, taxes: u32, cost_of_living: u32) bool {
return (income - taxes) > cost_of_living;
}
In Zig the output is:
Test 1/1 contrived example...integer overflow
/home/andy/dev/zig/build/test.zig:11:20: 0x204267 in ??? (test)
return (income - taxes) > cost_of_living;
^
/home/andy/dev/zig/build/test.zig:7:38: 0x2040d8 in ??? (test)
std.testing.expect(!isValidSalary(income, taxes, cost_of_living));
^
It shows you right where the bug is. If the `-` was defined to be twos complement wraparound, isValidSalary would silently return the wrong data!
Note that if you build this zig code in ReleaseFast or ReleaseSmall mode, it would be actually undefined behavior. ReleaseSafe is available as a build mode that has both optimizations and safety on.
- nickmqb 8y agoYou're correct that Muon wouldn't catch that bug, but I think one can make a pretty strong case that it's an anti pattern to use unsigned integers for that kind of stuff anyway. It's actually the reason that the Muon standard library defines Array.count and List.count as _signed_ integers. Even though these fields should clearly never be negative, having them be unsigned would invite exactly the kinds of bugs that you demonstrate in your test case.
- int_19h 8y agoAs you say, it's off by default in ReleaseFast, which sounds like what most projects would use for shipping code, and what most users would be running. So the safety checks would mostly be confined to debug builds - and from experience with C++, that's not enough. Especially for integer overflow, where it's too easy to write code that works correctly on most inputs, but fails for large values - so those bugs usually manifest in real world use rather than in testing. I agree that it's better to panic rather than wrap around by default, so long as panic is guaranteed.