diff options
| -rw-r--r-- | lib/std/meta.zig | 54 | ||||
| -rw-r--r-- | lib/std/meta/trailer_flags.zig | 20 | ||||
| -rw-r--r-- | lib/std/zig/ast.zig | 2 | ||||
| -rw-r--r-- | src/astgen.zig | 14 | ||||
| -rw-r--r-- | src/ir.zig | 2 | ||||
| -rw-r--r-- | src/type.zig | 2 | ||||
| -rw-r--r-- | src/value.zig | 2 |
7 files changed, 56 insertions, 40 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| { diff --git a/src/astgen.zig b/src/astgen.zig index 5cf8e12587..3670cb260e 100644 --- a/src/astgen.zig +++ b/src/astgen.zig @@ -758,7 +758,7 @@ fn ptrSliceType(mod: *Module, scope: *Scope, src: usize, ptr_info: *ast.PtrInfo, }, child_type); } - var kw_args: std.meta.fieldInfo(zir.Inst.PtrType, "kw_args").field_type = .{}; + var kw_args: std.meta.fieldInfo(zir.Inst.PtrType, .kw_args).field_type = .{}; kw_args.size = size; kw_args.@"allowzero" = ptr_info.allowzero_token != null; if (ptr_info.align_info) |some| { @@ -2756,8 +2756,8 @@ pub fn addZIRInstSpecial( scope: *Scope, src: usize, comptime T: type, - positionals: std.meta.fieldInfo(T, "positionals").field_type, - kw_args: std.meta.fieldInfo(T, "kw_args").field_type, + positionals: std.meta.fieldInfo(T, .positionals).field_type, + kw_args: std.meta.fieldInfo(T, .kw_args).field_type, ) !*T { const gen_zir = scope.getGenZIR(); try gen_zir.instructions.ensureCapacity(mod.gpa, gen_zir.instructions.items.len + 1); @@ -2874,8 +2874,8 @@ pub fn addZIRInst( scope: *Scope, src: usize, comptime T: type, - positionals: std.meta.fieldInfo(T, "positionals").field_type, - kw_args: std.meta.fieldInfo(T, "kw_args").field_type, + positionals: std.meta.fieldInfo(T, .positionals).field_type, + kw_args: std.meta.fieldInfo(T, .kw_args).field_type, ) !*zir.Inst { const inst_special = try addZIRInstSpecial(mod, scope, src, T, positionals, kw_args); return &inst_special.base; @@ -2883,12 +2883,12 @@ pub fn addZIRInst( /// TODO The existence of this function is a workaround for a bug in stage1. pub fn addZIRInstConst(mod: *Module, scope: *Scope, src: usize, typed_value: TypedValue) !*zir.Inst { - const P = std.meta.fieldInfo(zir.Inst.Const, "positionals").field_type; + const P = std.meta.fieldInfo(zir.Inst.Const, .positionals).field_type; return addZIRInst(mod, scope, src, zir.Inst.Const, P{ .typed_value = typed_value }, .{}); } /// TODO The existence of this function is a workaround for a bug in stage1. pub fn addZIRInstLoop(mod: *Module, scope: *Scope, src: usize, body: zir.Module.Body) !*zir.Inst.Loop { - const P = std.meta.fieldInfo(zir.Inst.Loop, "positionals").field_type; + const P = std.meta.fieldInfo(zir.Inst.Loop, .positionals).field_type; return addZIRInstSpecial(mod, scope, src, zir.Inst.Loop, P{ .body = body }, .{}); } diff --git a/src/ir.zig b/src/ir.zig index dda625c735..e43397faba 100644 --- a/src/ir.zig +++ b/src/ir.zig @@ -189,7 +189,7 @@ pub const Inst = struct { } pub fn Args(comptime T: type) type { - return std.meta.fieldInfo(T, "args").field_type; + return std.meta.fieldInfo(T, .args).field_type; } /// Returns `null` if runtime-known. diff --git a/src/type.zig b/src/type.zig index 7d35200727..bb2e3b3bc2 100644 --- a/src/type.zig +++ b/src/type.zig @@ -3232,7 +3232,7 @@ pub const Type = extern union { } pub fn Data(comptime t: Tag) type { - return std.meta.fieldInfo(t.Type(), "data").field_type; + return std.meta.fieldInfo(t.Type(), .data).field_type; } }; diff --git a/src/value.zig b/src/value.zig index 4450099069..8180df2f9e 100644 --- a/src/value.zig +++ b/src/value.zig @@ -207,7 +207,7 @@ pub const Value = extern union { } pub fn Data(comptime t: Tag) type { - return std.meta.fieldInfo(t.Type(), "data").field_type; + return std.meta.fieldInfo(t.Type(), .data).field_type; } }; |
