authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-01-02 17:06:06+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-01-02 17:06:06+02:00
log332a43858a6ba2128d3df9e6bca45a10547ed383
tree31d0a0eb6fe120e0d375d58655cef8fe555b05b8
parentaadd1b252e1d912e45cc924a15872d7c3d1f9080

Sema: `@intToEnum` on non-exhaustive enum at comptime should check int is in range

Closes #14155

2 files changed, 32 insertions(+), 2 deletions(-)

src/Sema.zig+21-2
......@@ -2536,6 +2536,9 @@ fn coerceResultPtr(
25362536 .wrap_errunion_payload => {
25372537 new_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, new_ptr, false, true);
25382538 },
2539 .array_to_slice => {
2540 return sema.fail(block, src, "TODO coerce_result_ptr array_to_slice", .{});
2541 },
25392542 else => {
25402543 if (std.debug.runtime_safety) {
25412544 std.debug.panic("unexpected AIR tag for coerce_result_ptr: {}", .{
......@@ -7839,7 +7842,23 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
78397842
78407843 if (try sema.resolveMaybeUndefVal(operand)) |int_val| {
78417844 if (dest_ty.isNonexhaustiveEnum()) {
7842 return sema.addConstant(dest_ty, int_val);
7845 var buffer: Type.Payload.Bits = undefined;
7846 const int_tag_ty = dest_ty.intTagType(&buffer);
7847 if (try sema.intFitsInType(int_val, int_tag_ty, null)) {
7848 return sema.addConstant(dest_ty, int_val);
7849 }
7850 const msg = msg: {
7851 const msg = try sema.errMsg(
7852 block,
7853 src,
7854 "int value '{}' out of range of non-exhaustive enum '{}'",
7855 .{ int_val.fmtValue(sema.typeOf(operand), sema.mod), dest_ty.fmt(sema.mod) },
7856 );
7857 errdefer msg.destroy(sema.gpa);
7858 try sema.addDeclaredHereNote(msg, dest_ty);
7859 break :msg msg;
7860 };
7861 return sema.failWithOwnedErrorMsg(msg);
78437862 }
78447863 if (int_val.isUndef()) {
78457864 return sema.failWithUseOfUndef(block, operand_src);
......@@ -32886,7 +32905,7 @@ fn enumHasInt(
3288632905 int: Value,
3288732906) CompileError!bool {
3288832907 switch (ty.tag()) {
32889 .enum_nonexhaustive => return sema.intFitsInType(int, ty, null),
32908 .enum_nonexhaustive => unreachable,
3289032909 .enum_full => {
3289132910 const enum_full = ty.castTag(.enum_full).?.data;
3289232911 const tag_ty = enum_full.tag_ty;
test/cases/compile_errors/intToEnum_on_non-exhaustive_enums_checks_int_in_range.zig created+11
......@@ -0,0 +1,11 @@
1pub export fn entry() void {
2 const E = enum(u3) { a, b, c, _ };
3 @compileLog(@intToEnum(E, 100));
4}
5
6// error
7// target=native
8// backend=stage2
9//
10// :3:17: error: int value '100' out of range of non-exhaustive enum 'tmp.entry.E'
11// :2:15: note: enum declared here