commit e664bf4d81e9266ee4749b5da88cab4554499bf6 (tree)
parent bce6a7c21529e9b294a641b5d7472c000204aaef
Author: mlugg <mlugg@mlugg.co.uk>
Date: Wed, 30 Jul 2025 23:22:32 +0100
Sema: compile error on lossy int to float coercion
Resolves: #21586
Diffstat:
2 files changed, 39 insertions(+), 11 deletions(-)
diff --git a/src/Sema.zig b/src/Sema.zig
@@ -28733,17 +28733,36 @@ fn coerceExtra(
break :int;
};
const result_val = try val.floatFromIntAdvanced(sema.arena, inst_ty, dest_ty, pt, .sema);
- // TODO implement this compile error
- //const int_again_val = try result_val.intFromFloat(sema.arena, inst_ty);
- //if (!int_again_val.eql(val, inst_ty, zcu)) {
- // return sema.fail(
- // block,
- // inst_src,
- // "type '{f}' cannot represent integer value '{f}'",
- // .{ dest_ty.fmt(pt), val },
- // );
- //}
- return Air.internedToRef(result_val.toIntern());
+ const fits: bool = switch (ip.indexToKey(result_val.toIntern())) {
+ else => unreachable,
+ .undef => true,
+ .float => |float| fits: {
+ var buffer: InternPool.Key.Int.Storage.BigIntSpace = undefined;
+ const operand_big_int = val.toBigInt(&buffer, zcu);
+ switch (float.storage) {
+ inline else => |x| {
+ if (!std.math.isFinite(x)) break :fits false;
+ var result_big_int: std.math.big.int.Mutable = .{
+ .limbs = try sema.arena.alloc(std.math.big.Limb, std.math.big.int.calcLimbLen(x)),
+ .len = undefined,
+ .positive = undefined,
+ };
+ switch (result_big_int.setFloat(x, .nearest_even)) {
+ .inexact => break :fits false,
+ .exact => {},
+ }
+ break :fits result_big_int.toConst().eql(operand_big_int);
+ },
+ }
+ },
+ };
+ if (!fits) return sema.fail(
+ block,
+ inst_src,
+ "type '{f}' cannot represent integer value '{f}'",
+ .{ dest_ty.fmt(pt), val.fmtValue(pt) },
+ );
+ return .fromValue(result_val);
},
else => {},
},
diff --git a/test/cases/compile_errors/int_to_float_coercion_loses_precision.zig b/test/cases/compile_errors/int_to_float_coercion_loses_precision.zig
@@ -0,0 +1,9 @@
+export fn foo() void {
+ const int: u16 = 65535;
+ const float: f16 = int;
+ _ = float;
+}
+
+// error
+//
+// :3:24: error: type 'f16' cannot represent integer value '65535'