aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/meta.zig54
-rw-r--r--lib/std/meta/trailer_flags.zig20
-rw-r--r--lib/std/zig/ast.zig2
3 files changed, 46 insertions, 30 deletions
diff --git a/lib/std/meta.zig b/lib/std/meta.zig
index 70f12c0e9c..2c94569bf1 100644
--- a/lib/std/meta.zig
+++ b/lib/std/meta.zig
@@ -487,19 +487,14 @@ test "std.meta.fields" {
testing.expect(comptime uf[0].field_type == u8);
}
-pub fn fieldInfo(comptime T: type, comptime field_name: []const u8) switch (@typeInfo(T)) {
+pub fn fieldInfo(comptime T: type, comptime field: FieldEnum(T)) switch (@typeInfo(T)) {
.Struct => TypeInfo.StructField,
.Union => TypeInfo.UnionField,
.ErrorSet => TypeInfo.Error,
.Enum => TypeInfo.EnumField,
else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"),
} {
- inline for (comptime fields(T)) |field| {
- if (comptime mem.eql(u8, field.name, field_name))
- return field;
- }
-
- @compileError("'" ++ @typeName(T) ++ "' has no field '" ++ field_name ++ "'");
+ return fields(T)[@enumToInt(field)];
}
test "std.meta.fieldInfo" {
@@ -514,10 +509,10 @@ test "std.meta.fieldInfo" {
a: u8,
};
- const e1f = comptime fieldInfo(E1, "A");
- const e2f = comptime fieldInfo(E2, "A");
- const sf = comptime fieldInfo(S1, "a");
- const uf = comptime fieldInfo(U1, "a");
+ const e1f = fieldInfo(E1, .A);
+ const e2f = fieldInfo(E2, .A);
+ const sf = fieldInfo(S1, .a);
+ const uf = fieldInfo(U1, .a);
testing.expect(mem.eql(u8, e1f.name, "A"));
testing.expect(mem.eql(u8, e2f.name, "A"));
@@ -568,6 +563,43 @@ test "std.meta.fieldNames" {
testing.expectEqualSlices(u8, u1names[1], "b");
}
+pub fn FieldEnum(comptime T: type) type {
+ const fieldInfos = fields(T);
+ var enumFields: [fieldInfos.len]std.builtin.TypeInfo.EnumField = undefined;
+ var decls = [_]std.builtin.TypeInfo.Declaration{};
+ inline for (fieldInfos) |field, i| {
+ enumFields[i] = .{
+ .name = field.name,
+ .value = i,
+ };
+ }
+ return @Type(.{
+ .Enum = .{
+ .layout = .Auto,
+ .tag_type = std.math.IntFittingRange(0, fieldInfos.len - 1),
+ .fields = &enumFields,
+ .decls = &decls,
+ .is_exhaustive = true,
+ },
+ });
+}
+
+fn expectEqualEnum(expected: anytype, actual: @TypeOf(expected)) void {
+ // TODO: https://github.com/ziglang/zig/issues/7419
+ // testing.expectEqual(@typeInfo(expected).Enum, @typeInfo(actual).Enum);
+ testing.expectEqual(@typeInfo(expected).Enum.layout, @typeInfo(actual).Enum.layout);
+ testing.expectEqual(@typeInfo(expected).Enum.tag_type, @typeInfo(actual).Enum.tag_type);
+ comptime testing.expectEqualSlices(std.builtin.TypeInfo.EnumField, @typeInfo(expected).Enum.fields, @typeInfo(actual).Enum.fields);
+ comptime testing.expectEqualSlices(std.builtin.TypeInfo.Declaration, @typeInfo(expected).Enum.decls, @typeInfo(actual).Enum.decls);
+ testing.expectEqual(@typeInfo(expected).Enum.is_exhaustive, @typeInfo(actual).Enum.is_exhaustive);
+}
+
+test "std.meta.FieldEnum" {
+ expectEqualEnum(enum { a }, FieldEnum(struct { a: u8 }));
+ expectEqualEnum(enum { a, b, c }, FieldEnum(struct { a: u8, b: void, c: f32 }));
+ expectEqualEnum(enum { a, b, c }, FieldEnum(union { a: u8, b: void, c: f32 }));
+}
+
pub fn TagType(comptime T: type) type {
return switch (@typeInfo(T)) {
.Enum => |info| info.tag_type,
diff --git a/lib/std/meta/trailer_flags.zig b/lib/std/meta/trailer_flags.zig
index 40fbc57dfe..a5882d9e1b 100644
--- a/lib/std/meta/trailer_flags.zig
+++ b/lib/std/meta/trailer_flags.zig
@@ -21,20 +21,7 @@ pub fn TrailerFlags(comptime Fields: type) type {
pub const Int = meta.Int(.unsigned, bit_count);
pub const bit_count = @typeInfo(Fields).Struct.fields.len;
- pub const FieldEnum = blk: {
- comptime var fields: [bit_count]TypeInfo.EnumField = undefined;
- inline for (@typeInfo(Fields).Struct.fields) |struct_field, i|
- fields[i] = .{ .name = struct_field.name, .value = i };
- break :blk @Type(.{
- .Enum = .{
- .layout = .Auto,
- .tag_type = std.math.IntFittingRange(0, bit_count - 1),
- .fields = &fields,
- .decls = &[_]TypeInfo.Declaration{},
- .is_exhaustive = true,
- },
- });
- };
+ pub const FieldEnum = std.meta.FieldEnum(Fields);
pub const InitStruct = blk: {
comptime var fields: [bit_count]TypeInfo.StructField = undefined;
@@ -135,10 +122,7 @@ pub fn TrailerFlags(comptime Fields: type) type {
}
pub fn Field(comptime field: FieldEnum) type {
- inline for (@typeInfo(Fields).Struct.fields) |field_info, i| {
- if (i == @enumToInt(field))
- return field_info.field_type;
- }
+ return @typeInfo(Fields).Struct.fields[@enumToInt(field)].field_type;
}
pub fn sizeInBytes(self: Self) usize {
diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig
index 9e191ee5fe..c0e72ea822 100644
--- a/lib/std/zig/ast.zig
+++ b/lib/std/zig/ast.zig
@@ -688,7 +688,7 @@ pub const Node = struct {
/// Prefer `castTag` to this.
pub fn cast(base: *Node, comptime T: type) ?*T {
- if (std.meta.fieldInfo(T, "base").default_value) |default_base| {
+ if (std.meta.fieldInfo(T, .base).default_value) |default_base| {
return base.castTag(default_base.tag);
}
inline for (@typeInfo(Tag).Enum.fields) |field| {