authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-08-17 17:10:08-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-08-17 17:10:08-04:00
log7f0642b5d3c67f93892430f502f4eadbe54f1989
tree9c323487031224f7d169b419ecfb74c3eb3b7a9b
parent070282a96ec23fb41041843d5753608ec5090f8b
parent2cccd144914d8715894458f317fa4c3c572cdcad
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #12397 from martinhath/issue-12364

Sema: error on ambiguous coercion of comptime float and ints

3 files changed, 42 insertions(+), 4 deletions(-)

src/Sema.zig+15
...@@ -11202,6 +11202,21 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -11202,6 +11202,21 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
11202 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(block, lhs_src, casted_lhs);11202 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(block, lhs_src, casted_lhs);
11203 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(block, rhs_src, casted_rhs);11203 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(block, rhs_src, casted_rhs);
1120411204
11205 if ((lhs_ty.zigTypeTag() == .ComptimeFloat and rhs_ty.zigTypeTag() == .ComptimeInt) or
11206 (lhs_ty.zigTypeTag() == .ComptimeInt and rhs_ty.zigTypeTag() == .ComptimeFloat))
11207 {
11208 // If it makes a difference whether we coerce to ints or floats before doing the division, error.
11209 // If lhs % rhs is 0, it doesn't matter.
11210 const lhs_val = maybe_lhs_val orelse unreachable;
11211 const rhs_val = maybe_rhs_val orelse unreachable;
11212 const rem = lhs_val.floatRem(rhs_val, resolved_type, sema.arena, target) catch unreachable;
11213 if (rem.compareWithZero(.neq)) {
11214 return sema.fail(block, src, "ambiguous coercion of division operands '{s}' and '{s}'; non-zero remainder '{}'", .{
11215 @tagName(lhs_ty.tag()), @tagName(rhs_ty.tag()), rem.fmtValue(resolved_type, sema.mod),
11216 });
11217 }
11218 }
11219
11205 // TODO: emit compile error when .div is used on integers and there would be an11220 // TODO: emit compile error when .div is used on integers and there would be an
11206 // ambiguous result between div_floor and div_trunc.11221 // ambiguous result between div_floor and div_trunc.
1120711222
test/behavior/floatop.zig+4-4
...@@ -194,8 +194,8 @@ fn testSin() !void {...@@ -194,8 +194,8 @@ fn testSin() !void {
194 const eps = epsForType(ty);194 const eps = epsForType(ty);
195 try expect(@sin(@as(ty, 0)) == 0);195 try expect(@sin(@as(ty, 0)) == 0);
196 try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi)), 0, eps));196 try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi)), 0, eps));
197 try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi / 2)), 1, eps));197 try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi / 2.0)), 1, eps));
198 try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi / 4)), 0.7071067811865475, eps));198 try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi / 4.0)), 0.7071067811865475, eps));
199 }199 }
200200
201 {201 {
...@@ -228,8 +228,8 @@ fn testCos() !void {...@@ -228,8 +228,8 @@ fn testCos() !void {
228 const eps = epsForType(ty);228 const eps = epsForType(ty);
229 try expect(@cos(@as(ty, 0)) == 1);229 try expect(@cos(@as(ty, 0)) == 1);
230 try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi)), -1, eps));230 try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi)), -1, eps));
231 try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi / 2)), 0, eps));231 try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi / 2.0)), 0, eps));
232 try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi / 4)), 0.7071067811865475, eps));232 try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi / 4.0)), 0.7071067811865475, eps));
233 }233 }
234234
235 {235 {
test/cases/compile_errors/ambiguous_coercion_of_division_operands.zig created+23
...@@ -0,0 +1,23 @@
1export fn entry1() void {
2 var f: f32 = 54.0 / 5;
3 _ = f;
4}
5export fn entry2() void {
6 var f: f32 = 54 / 5.0;
7 _ = f;
8}
9export fn entry3() void {
10 var f: f32 = 55.0 / 5;
11 _ = f;
12}
13export fn entry4() void {
14 var f: f32 = 55 / 5.0;
15 _ = f;
16}
17
18// error
19// backend=stage2
20// target=native
21//
22// :2:23: error: ambiguous coercion of division operands 'comptime_float' and 'comptime_int'; non-zero remainder '4'
23// :6:21: error: ambiguous coercion of division operands 'comptime_int' and 'comptime_float'; non-zero remainder '4'