authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-07-30 23:22:32+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-07-31 10:57:04+01:00
loge664bf4d81e9266ee4749b5da88cab4554499bf6
tree8b5beea3fb60fd020bf8ce4ba5cf6d9a9cfe398b
parentbce6a7c21529e9b294a641b5d7472c000204aaef
signaturelock-open Commit is signed but in an unrecognized format.

Sema: compile error on lossy int to float coercion

Resolves: #21586

2 files changed, 39 insertions(+), 11 deletions(-)

src/Sema.zig+30-11
...@@ -28733,17 +28733,36 @@ fn coerceExtra(...@@ -28733,17 +28733,36 @@ fn coerceExtra(
28733 break :int;28733 break :int;
28734 };28734 };
28735 const result_val = try val.floatFromIntAdvanced(sema.arena, inst_ty, dest_ty, pt, .sema);28735 const result_val = try val.floatFromIntAdvanced(sema.arena, inst_ty, dest_ty, pt, .sema);
28736 // TODO implement this compile error28736 const fits: bool = switch (ip.indexToKey(result_val.toIntern())) {
28737 //const int_again_val = try result_val.intFromFloat(sema.arena, inst_ty);28737 else => unreachable,
28738 //if (!int_again_val.eql(val, inst_ty, zcu)) {28738 .undef => true,
28739 // return sema.fail(28739 .float => |float| fits: {
28740 // block,28740 var buffer: InternPool.Key.Int.Storage.BigIntSpace = undefined;
28741 // inst_src,28741 const operand_big_int = val.toBigInt(&buffer, zcu);
28742 // "type '{f}' cannot represent integer value '{f}'",28742 switch (float.storage) {
28743 // .{ dest_ty.fmt(pt), val },28743 inline else => |x| {
28744 // );28744 if (!std.math.isFinite(x)) break :fits false;
28745 //}28745 var result_big_int: std.math.big.int.Mutable = .{
28746 return Air.internedToRef(result_val.toIntern());28746 .limbs = try sema.arena.alloc(std.math.big.Limb, std.math.big.int.calcLimbLen(x)),
28747 .len = undefined,
28748 .positive = undefined,
28749 };
28750 switch (result_big_int.setFloat(x, .nearest_even)) {
28751 .inexact => break :fits false,
28752 .exact => {},
28753 }
28754 break :fits result_big_int.toConst().eql(operand_big_int);
28755 },
28756 }
28757 },
28758 };
28759 if (!fits) return sema.fail(
28760 block,
28761 inst_src,
28762 "type '{f}' cannot represent integer value '{f}'",
28763 .{ dest_ty.fmt(pt), val.fmtValue(pt) },
28764 );
28765 return .fromValue(result_val);
28747 },28766 },
28748 else => {},28767 else => {},
28749 },28768 },
test/cases/compile_errors/int_to_float_coercion_loses_precision.zig created+9
...@@ -0,0 +1,9 @@
1export fn foo() void {
2 const int: u16 = 65535;
3 const float: f16 = int;
4 _ = float;
5}
6
7// error
8//
9// :3:24: error: type 'f16' cannot represent integer value '65535'