Skip to content

Commit e963793

Browse files
authored
Updates std.meta.intToEnum to support non-exhaustive enums (#15491)
This was preventing `std.json` from deserializing non-exhaustive enums.
1 parent 6ae19fa commit e963793

File tree

1 file changed

+16
-1
lines changed

1 file changed

+16
-1
lines changed

lib/std/meta.zig

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -965,18 +965,33 @@ test "intToEnum with error return" {
965965
A,
966966
B,
967967
};
968+
const E3 = enum(i8) { A, _ };
968969

969970
var zero: u8 = 0;
970971
var one: u16 = 1;
971972
try testing.expect(intToEnum(E1, zero) catch unreachable == E1.A);
972973
try testing.expect(intToEnum(E2, one) catch unreachable == E2.B);
974+
try testing.expect(intToEnum(E3, zero) catch unreachable == E3.A);
975+
try testing.expect(intToEnum(E3, 127) catch unreachable == @intToEnum(E3, 127));
976+
try testing.expect(intToEnum(E3, -128) catch unreachable == @intToEnum(E3, -128));
973977
try testing.expectError(error.InvalidEnumTag, intToEnum(E1, one));
978+
try testing.expectError(error.InvalidEnumTag, intToEnum(E3, 128));
979+
try testing.expectError(error.InvalidEnumTag, intToEnum(E3, -129));
974980
}
975981

976982
pub const IntToEnumError = error{InvalidEnumTag};
977983

978984
pub fn intToEnum(comptime EnumTag: type, tag_int: anytype) IntToEnumError!EnumTag {
979-
inline for (@typeInfo(EnumTag).Enum.fields) |f| {
985+
const enum_info = @typeInfo(EnumTag).Enum;
986+
987+
if (!enum_info.is_exhaustive) {
988+
if (std.math.cast(enum_info.tag_type, tag_int)) |tag| {
989+
return @intToEnum(EnumTag, tag);
990+
}
991+
return error.InvalidEnumTag;
992+
}
993+
994+
inline for (enum_info.fields) |f| {
980995
const this_tag_value = @field(EnumTag, f.name);
981996
if (tag_int == @enumToInt(this_tag_value)) {
982997
return this_tag_value;

0 commit comments

Comments
 (0)