Skip to content

Commit 7c7d9e1

Browse files
committed
Sema: fix runtime int to enum with one possible value
1 parent d0a5ad0 commit 7c7d9e1

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

src/Sema.zig

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7372,9 +7372,23 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
73727372
return sema.addConstant(dest_ty, int_val);
73737373
}
73747374

7375+
if (try sema.typeHasOnePossibleValue(block, operand_src, dest_ty)) |opv| {
7376+
const result = try sema.addConstant(dest_ty, opv);
7377+
// The operand is runtime-known but the result is comptime-known. In
7378+
// this case we still need a safety check.
7379+
// TODO add a safety check here. we can't use is_named_enum_value -
7380+
// it needs to convert the enum back to int and make sure it equals the operand int.
7381+
return result;
7382+
}
7383+
73757384
try sema.requireRuntimeBlock(block, src, operand_src);
73767385
const result = try block.addTyOp(.intcast, dest_ty, operand);
7377-
if (block.wantSafety() and !dest_ty.isNonexhaustiveEnum() and sema.mod.comp.bin_file.options.use_llvm) {
7386+
if (block.wantSafety() and
7387+
!dest_ty.isNonexhaustiveEnum() and
7388+
// TODO instead of "use_llvm", check a different condition so that backends
7389+
// can advertise themselves as supporting these extra AIR instructions for safety.
7390+
sema.mod.comp.bin_file.options.use_llvm)
7391+
{
73787392
const ok = try block.addUnOp(.is_named_enum_value, result);
73797393
try sema.addSafetyCheck(block, ok, .invalid_enum_value);
73807394
}

test/behavior/enum.zig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,3 +1169,11 @@ test "Non-exhaustive enum with nonstandard int size behaves correctly" {
11691169
const E = enum(u15) { _ };
11701170
try expect(@sizeOf(E) == @sizeOf(u15));
11711171
}
1172+
1173+
test "runtime int to enum with one possible value" {
1174+
const E = enum { one };
1175+
var runtime: usize = 0;
1176+
if (@intToEnum(E, runtime) != .one) {
1177+
@compileError("test failed");
1178+
}
1179+
}

0 commit comments

Comments
 (0)