zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 7c7d9e13d77de7b9321623c73b6566a3bcbe367c (tree)
parent d0a5ad0e4c74d36982dbc823dd80dc62395fe2bd
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Tue, 18 Oct 2022 09:58:12 -0700

Sema: fix runtime int to enum with one possible value

Diffstat:
Msrc/Sema.zig | 16+++++++++++++++-
Mtest/behavior/enum.zig | 8++++++++
2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/src/Sema.zig b/src/Sema.zig @@ -7372,9 +7372,23 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A return sema.addConstant(dest_ty, int_val); } + if (try sema.typeHasOnePossibleValue(block, operand_src, dest_ty)) |opv| { + const result = try sema.addConstant(dest_ty, opv); + // The operand is runtime-known but the result is comptime-known. In + // this case we still need a safety check. + // TODO add a safety check here. we can't use is_named_enum_value - + // it needs to convert the enum back to int and make sure it equals the operand int. + return result; + } + try sema.requireRuntimeBlock(block, src, operand_src); const result = try block.addTyOp(.intcast, dest_ty, operand); - if (block.wantSafety() and !dest_ty.isNonexhaustiveEnum() and sema.mod.comp.bin_file.options.use_llvm) { + if (block.wantSafety() and + !dest_ty.isNonexhaustiveEnum() and + // TODO instead of "use_llvm", check a different condition so that backends + // can advertise themselves as supporting these extra AIR instructions for safety. + sema.mod.comp.bin_file.options.use_llvm) + { const ok = try block.addUnOp(.is_named_enum_value, result); try sema.addSafetyCheck(block, ok, .invalid_enum_value); } diff --git a/test/behavior/enum.zig b/test/behavior/enum.zig @@ -1169,3 +1169,11 @@ test "Non-exhaustive enum with nonstandard int size behaves correctly" { const E = enum(u15) { _ }; try expect(@sizeOf(E) == @sizeOf(u15)); } + +test "runtime int to enum with one possible value" { + const E = enum { one }; + var runtime: usize = 0; + if (@intToEnum(E, runtime) != .one) { + @compileError("test failed"); + } +}