Sema: compile error on lossy int to float coercion

Resolves: #21586
This commit is contained in:
mlugg 2025-07-30 23:22:32 +01:00
parent bce6a7c215
commit e664bf4d81
No known key found for this signature in database
GPG key ID: 3F5B7DCCBF4AF02E
2 changed files with 39 additions and 11 deletions

View file

@ -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 => {},
},

View file

@ -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'