diff options
| author | Matthew Lugg <mlugg@mlugg.co.uk> | 2025-07-31 21:49:37 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-31 21:49:37 +0100 |
| commit | 04d7b491b436f67e51a17ba6fb49de862fa7bb8c (patch) | |
| tree | 822bb5cf73747ba4c82aea49ecc4fc777a9c5979 /src/Sema.zig | |
| parent | 982c387753c33a9eb42349c109fc4a6ed0675165 (diff) | |
| parent | 64bf8bb146099b51d74635a1f116a913e442bcf4 (diff) | |
| download | zig-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.zig | 41 |
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 => {}, }, |
