authorgravatar for silver@silv.reSilver <silver@silv.re> 2022-09-20 14:40:43+01:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-09-27 18:42:20+03:00
logf3a1b5c481646ee35813cbe8bb2b0a3979df3ab8
treef23e0b996c607c5c6782d2e5ba7ad6c90f7679c6
parentc75e8f3616d895d213faad5ad2678d3997f17d8a

std/meta: make FieldEnum(T) == Tag(T) for tagged unions when values match field indices


1 files changed, 23 insertions(+), 0 deletions(-)

lib/std/meta.zig+23
...@@ -606,6 +606,18 @@ test "std.meta.tags" {...@@ -606,6 +606,18 @@ test "std.meta.tags" {
606606
607pub fn FieldEnum(comptime T: type) type {607pub fn FieldEnum(comptime T: type) type {
608 const field_infos = fields(T);608 const field_infos = fields(T);
609
610 if (@typeInfo(T) == .Union) {
611 if (@typeInfo(T).Union.tag_type) |tag_type| {
612 for (std.enums.values(tag_type)) |v, i| {
613 if (@enumToInt(v) != i) break; // enum values not consecutive
614 if (!std.mem.eql(u8, @tagName(v), field_infos[i].name)) break; // fields out of order
615 } else {
616 return tag_type;
617 }
618 }
619 }
620
609 var enumFields: [field_infos.len]std.builtin.Type.EnumField = undefined;621 var enumFields: [field_infos.len]std.builtin.Type.EnumField = undefined;
610 var decls = [_]std.builtin.Type.Declaration{};622 var decls = [_]std.builtin.Type.Declaration{};
611 inline for (field_infos) |field, i| {623 inline for (field_infos) |field, i| {
...@@ -669,6 +681,17 @@ test "std.meta.FieldEnum" {...@@ -669,6 +681,17 @@ test "std.meta.FieldEnum" {
669 try expectEqualEnum(enum { a }, FieldEnum(struct { a: u8 }));681 try expectEqualEnum(enum { a }, FieldEnum(struct { a: u8 }));
670 try expectEqualEnum(enum { a, b, c }, FieldEnum(struct { a: u8, b: void, c: f32 }));682 try expectEqualEnum(enum { a, b, c }, FieldEnum(struct { a: u8, b: void, c: f32 }));
671 try expectEqualEnum(enum { a, b, c }, FieldEnum(union { a: u8, b: void, c: f32 }));683 try expectEqualEnum(enum { a, b, c }, FieldEnum(union { a: u8, b: void, c: f32 }));
684
685 const Tagged = union(enum) { a: u8, b: void, c: f32 };
686 try testing.expectEqual(Tag(Tagged), FieldEnum(Tagged));
687
688 const Tag2 = enum { b, c, a };
689 const Tagged2 = union(Tag2) { a: u8, b: void, c: f32 };
690 try testing.expect(Tag(Tagged2) != FieldEnum(Tagged2));
691
692 const Tag3 = enum(u8) { a, b, c = 7 };
693 const Tagged3 = union(Tag3) { a: u8, b: void, c: f32 };
694 try testing.expect(Tag(Tagged3) != FieldEnum(Tagged3));
672}695}
673696
674pub fn DeclEnum(comptime T: type) type {697pub fn DeclEnum(comptime T: type) type {