aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorMatthew Lugg <mlugg@mlugg.co.uk>2025-07-31 21:49:37 +0100
committerGitHub <noreply@github.com>2025-07-31 21:49:37 +0100
commit04d7b491b436f67e51a17ba6fb49de862fa7bb8c (patch)
tree822bb5cf73747ba4c82aea49ecc4fc777a9c5979 /src/Sema.zig
parent982c387753c33a9eb42349c109fc4a6ed0675165 (diff)
parent64bf8bb146099b51d74635a1f116a913e442bcf4 (diff)
downloadzig-04d7b491b436f67e51a17ba6fb49de862fa7bb8c.tar.gz
zig-04d7b491b436f67e51a17ba6fb49de862fa7bb8c.zip
Merge pull request #24632 from mlugg/lossy-int-to-float-coercion
Sema: compile error on lossy int to float coercion
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 5f22e48530..f81bb15f87 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -28745,17 +28745,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 => {},
},