aboutsummaryrefslogtreecommitdiff
path: root/lib/std/meta.zig
diff options
context:
space:
mode:
authorSilver <silver@silv.re>2022-09-20 14:40:43 +0100
committerVeikka Tuominen <git@vexu.eu>2022-09-27 18:42:20 +0300
commitf3a1b5c481646ee35813cbe8bb2b0a3979df3ab8 (patch)
treef23e0b996c607c5c6782d2e5ba7ad6c90f7679c6 /lib/std/meta.zig
parentc75e8f3616d895d213faad5ad2678d3997f17d8a (diff)
downloadzig-f3a1b5c481646ee35813cbe8bb2b0a3979df3ab8.tar.gz
zig-f3a1b5c481646ee35813cbe8bb2b0a3979df3ab8.zip
std/meta: make FieldEnum(T) == Tag(T) for tagged unions when values match field indices
Diffstat (limited to 'lib/std/meta.zig')
-rw-r--r--lib/std/meta.zig23
1 files changed, 23 insertions, 0 deletions
diff --git a/lib/std/meta.zig b/lib/std/meta.zig
index 993d88eb04..3396a4122c 100644
--- a/lib/std/meta.zig
+++ b/lib/std/meta.zig
@@ -606,6 +606,18 @@ test "std.meta.tags" {
pub fn FieldEnum(comptime T: type) type {
const field_infos = fields(T);
+
+ if (@typeInfo(T) == .Union) {
+ if (@typeInfo(T).Union.tag_type) |tag_type| {
+ for (std.enums.values(tag_type)) |v, i| {
+ if (@enumToInt(v) != i) break; // enum values not consecutive
+ if (!std.mem.eql(u8, @tagName(v), field_infos[i].name)) break; // fields out of order
+ } else {
+ return tag_type;
+ }
+ }
+ }
+
var enumFields: [field_infos.len]std.builtin.Type.EnumField = undefined;
var decls = [_]std.builtin.Type.Declaration{};
inline for (field_infos) |field, i| {
@@ -669,6 +681,17 @@ test "std.meta.FieldEnum" {
try expectEqualEnum(enum { a }, FieldEnum(struct { a: u8 }));
try expectEqualEnum(enum { a, b, c }, FieldEnum(struct { a: u8, b: void, c: f32 }));
try expectEqualEnum(enum { a, b, c }, FieldEnum(union { a: u8, b: void, c: f32 }));
+
+ const Tagged = union(enum) { a: u8, b: void, c: f32 };
+ try testing.expectEqual(Tag(Tagged), FieldEnum(Tagged));
+
+ const Tag2 = enum { b, c, a };
+ const Tagged2 = union(Tag2) { a: u8, b: void, c: f32 };
+ try testing.expect(Tag(Tagged2) != FieldEnum(Tagged2));
+
+ const Tag3 = enum(u8) { a, b, c = 7 };
+ const Tagged3 = union(Tag3) { a: u8, b: void, c: f32 };
+ try testing.expect(Tag(Tagged3) != FieldEnum(Tagged3));
}
pub fn DeclEnum(comptime T: type) type {