zig
zig copied to clipboard
divExact not panicking for floats at runtime
Zig Version
0.12.0-dev.3652+a59ad719d
Steps to Reproduce and Observed Behavior
Code:
const std = @import("std");
pub fn main() void {
var a: f32 = 5.0;
var b: f32 = 2.0;
_ = &a;
_ = &b;
std.debug.print("{}\n", .{ @divExact(a, b) });
}
Output:
$ zig run a.zig
2e0
But at compile time: Code:
const std = @import("std");
pub fn main() void {
const a: f32 = 5.0;
const b: f32 = 2.0;
_ = &a;
_ = &b;
std.debug.print("{}\n", .{ @divExact(a, b) });
}
Output:
$ zig build-exe a.zig
a.zig:8:32: error: exact division produced remainder
std.debug.print("{}\n", .{ @divExact(a, b) });
^~~~~~~~~~~~~~~
referenced by:
callMain: /usr/lib/zig/lib/std/start.zig:501:17
callMainWithArgs: /usr/lib/zig/lib/std/start.zig:469:12
remaining reference traces hidden; use '-freference-trace' to see all reference traces
Expected Behavior
The program panic at runtime when "division produced remainder".
The safety check uses .div_trunc and then .floors the result and checks if they match, but for floats .div_trunc doesn't produce remainder so the floored result is always the same:
https://github.com/ziglang/zig/blob/e45bdc6bd6e47ec3f7a06dbb48f24e842bf43a0d/src/Sema.zig#L15331-L15348
Using .div_float for floats fixes it:
diff --git a/src/Sema.zig b/src/Sema.zig
index d3989f630c..5044eb1d71 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -15328,7 +15328,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
try sema.addDivIntOverflowSafety(block, src, resolved_type, lhs_scalar_ty, maybe_lhs_val, maybe_rhs_val, casted_lhs, casted_rhs, is_int);
try sema.addDivByZeroSafety(block, src, resolved_type, maybe_rhs_val, casted_rhs, is_int);
- const result = try block.addBinOp(.div_trunc, casted_lhs, casted_rhs);
+ const result = try block.addBinOp(if (is_int) .div_trunc else .div_float, casted_lhs, casted_rhs);
const ok = if (!is_int) ok: {
const floored = try block.addUnOp(.floor, result);