Summary
t27c gen (Zig backend) emits a plain % for a remainder whose operands are signed integers (or floats). Zig refuses that at compile time, so any spec that takes % of an i32 parameter does not compile under zig test at all.
Found by the t27b differential test. Part of #5905.
Reproducer
module Sem;
fn inc(x: i32) -> i32 {
return x + 1;
}
fn shr(x: i32, n: i32) -> i32 {
return x >> n;
}
fn rem(a: i32, b: i32) -> i32 {
return a % b;
}
test inc_max { assert_eq(inc(2147483647), 0 - 2147483647 - 1); }
test shr_big { assert_eq(shr(1024, 40), 0); }
test rem_neg { assert_eq(rem(0 - 7, 2), 0 - 1); }
endmodule
t27c gen sem.t27 > sem.zig && zig test sem.zig
Observed
error: remainder division with 'i32' and 'i32': signed integers and floats must use @rem or @mod
The whole file fails to compile, so inc_max and shr_big are never run either.
Expected
a % b on signed operands lowers to @rem(a, b): the truncated remainder, rem(-7, 2) == -1, which is what C, Rust and t27b compute. Unsigned % stays %.
/ already has this repair (W593 emits @divTrunc when an operand is known signed); % was never given the same rule. Zig refuses runtime float % with the same message, so floats need @rem too.
Summary
t27c gen(Zig backend) emits a plain%for a remainder whose operands are signed integers (or floats). Zig refuses that at compile time, so any spec that takes%of ani32parameter does not compile underzig testat all.Found by the t27b differential test. Part of #5905.
Reproducer
t27c gen sem.t27 > sem.zig && zig test sem.zigObserved
The whole file fails to compile, so
inc_maxandshr_bigare never run either.Expected
a % bon signed operands lowers to@rem(a, b): the truncated remainder,rem(-7, 2) == -1, which is what C, Rust and t27b compute. Unsigned%stays%./already has this repair (W593 emits@divTruncwhen an operand is known signed);%was never given the same rule. Zig refuses runtime float%with the same message, so floats need@remtoo.