diff --git a/src/InternPool.zig b/src/InternPool.zig index 221b56b88aff..f92711d4f1ba 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -443,14 +443,12 @@ pub const Key = union(enum) { return @intCast(u32, field_index); } // Auto-numbered enum. Convert `int_tag_val` to field index. - switch (ip.indexToKey(int_tag_val).int.storage) { - .u64 => |x| { - if (x >= self.names.len) return null; - return @intCast(u32, x); - }, - .i64, .big_int => return null, // out of range + const field_index = switch (ip.indexToKey(int_tag_val).int.storage) { + inline .u64, .i64 => |x| std.math.cast(u32, x) orelse return null, + .big_int => |x| x.to(u32) catch return null, .lazy_align, .lazy_size => unreachable, - } + }; + return if (field_index < self.names.len) field_index else null; } }; diff --git a/test/behavior/enum.zig b/test/behavior/enum.zig index 12926800e307..1076f5e3ea34 100644 --- a/test/behavior/enum.zig +++ b/test/behavior/enum.zig @@ -1197,3 +1197,18 @@ test "enum tag from a local variable" { const i = @enumFromInt(S.Int(u32), 0); try std.testing.expect(@intFromEnum(i) == 0); } + +test "auto-numbered enum with signed tag type" { + const E = enum(i32) { a, b }; + + try std.testing.expectEqual(@as(i32, 0), @intFromEnum(E.a)); + try std.testing.expectEqual(@as(i32, 1), @intFromEnum(E.b)); + try std.testing.expectEqual(E.a, @enumFromInt(E, 0)); + try std.testing.expectEqual(E.b, @enumFromInt(E, 1)); + try std.testing.expectEqual(E.a, @enumFromInt(E, @as(i32, 0))); + try std.testing.expectEqual(E.b, @enumFromInt(E, @as(i32, 1))); + try std.testing.expectEqual(E.a, @enumFromInt(E, @as(u32, 0))); + try std.testing.expectEqual(E.b, @enumFromInt(E, @as(u32, 1))); + try std.testing.expectEqualStrings("a", @tagName(E.a)); + try std.testing.expectEqualStrings("b", @tagName(E.b)); +}