aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authormlugg <mlugg@mlugg.co.uk>2025-07-30 23:22:32 +0100
committermlugg <mlugg@mlugg.co.uk>2025-07-31 10:57:04 +0100
commite664bf4d81e9266ee4749b5da88cab4554499bf6 (patch)
tree8b5beea3fb60fd020bf8ce4ba5cf6d9a9cfe398b /src/Sema.zig
parentbce6a7c21529e9b294a641b5d7472c000204aaef (diff)
downloadzig-e664bf4d81e9266ee4749b5da88cab4554499bf6.tar.gz
zig-e664bf4d81e9266ee4749b5da88cab4554499bf6.zip
Sema: compile error on lossy int to float coercion
Resolves: #21586
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig41
1 files changed, 30 insertions, 11 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 94bf21e03b..edba4e6874 100644
--- 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 => {},
},