Skip to content

Commit e664bf4

Browse files
committed
Sema: compile error on lossy int to float coercion
Resolves: #21586
1 parent bce6a7c commit e664bf4

File tree

2 files changed

+39
-11
lines changed

2 files changed

+39
-11
lines changed

src/Sema.zig

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28733,17 +28733,36 @@ fn coerceExtra(
2873328733
break :int;
2873428734
};
2873528735
const result_val = try val.floatFromIntAdvanced(sema.arena, inst_ty, dest_ty, pt, .sema);
28736-
// TODO implement this compile error
28737-
//const int_again_val = try result_val.intFromFloat(sema.arena, inst_ty);
28738-
//if (!int_again_val.eql(val, inst_ty, zcu)) {
28739-
// return sema.fail(
28740-
// block,
28741-
// inst_src,
28742-
// "type '{f}' cannot represent integer value '{f}'",
28743-
// .{ dest_ty.fmt(pt), val },
28744-
// );
28745-
//}
28746-
return Air.internedToRef(result_val.toIntern());
28736+
const fits: bool = switch (ip.indexToKey(result_val.toIntern())) {
28737+
else => unreachable,
28738+
.undef => true,
28739+
.float => |float| fits: {
28740+
var buffer: InternPool.Key.Int.Storage.BigIntSpace = undefined;
28741+
const operand_big_int = val.toBigInt(&buffer, zcu);
28742+
switch (float.storage) {
28743+
inline else => |x| {
28744+
if (!std.math.isFinite(x)) break :fits false;
28745+
var result_big_int: std.math.big.int.Mutable = .{
28746+
.limbs = try sema.arena.alloc(std.math.big.Limb, std.math.big.int.calcLimbLen(x)),
28747+
.len = undefined,
28748+
.positive = undefined,
28749+
};
28750+
switch (result_big_int.setFloat(x, .nearest_even)) {
28751+
.inexact => break :fits false,
28752+
.exact => {},
28753+
}
28754+
break :fits result_big_int.toConst().eql(operand_big_int);
28755+
},
28756+
}
28757+
},
28758+
};
28759+
if (!fits) return sema.fail(
28760+
block,
28761+
inst_src,
28762+
"type '{f}' cannot represent integer value '{f}'",
28763+
.{ dest_ty.fmt(pt), val.fmtValue(pt) },
28764+
);
28765+
return .fromValue(result_val);
2874728766
},
2874828767
else => {},
2874928768
},
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export fn foo() void {
2+
const int: u16 = 65535;
3+
const float: f16 = int;
4+
_ = float;
5+
}
6+
7+
// error
8+
//
9+
// :3:24: error: type 'f16' cannot represent integer value '65535'

0 commit comments

Comments
 (0)