authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-01 16:01:27-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-01 16:01:27-07:00
log3dafc5b9a322124c325447a37fa117b093795448
treeeff0492d8e0ce89af1e9908dc4febd68dc4ccf0e
parentc5ec096b2ffd42aff6385debe2a412a6db67868f
parentbbab5e19b45436f9828ae988832c1e31b5861683

Merge branch 'daurnimator-meta.fields'

closes #7420

7 files changed, 56 insertions(+), 40 deletions(-)

lib/std/meta.zig+43-11
......@@ -487,19 +487,14 @@ test "std.meta.fields" {
487487 testing.expect(comptime uf[0].field_type == u8);
488488}
489489
490pub fn fieldInfo(comptime T: type, comptime field_name: []const u8) switch (@typeInfo(T)) {
490pub fn fieldInfo(comptime T: type, comptime field: FieldEnum(T)) switch (@typeInfo(T)) {
491491 .Struct => TypeInfo.StructField,
492492 .Union => TypeInfo.UnionField,
493493 .ErrorSet => TypeInfo.Error,
494494 .Enum => TypeInfo.EnumField,
495495 else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"),
496496} {
497 inline for (comptime fields(T)) |field| {
498 if (comptime mem.eql(u8, field.name, field_name))
499 return field;
500 }
501
502 @compileError("'" ++ @typeName(T) ++ "' has no field '" ++ field_name ++ "'");
497 return fields(T)[@enumToInt(field)];
503498}
504499
505500test "std.meta.fieldInfo" {
......@@ -514,10 +509,10 @@ test "std.meta.fieldInfo" {
514509 a: u8,
515510 };
516511
517 const e1f = comptime fieldInfo(E1, "A");
518 const e2f = comptime fieldInfo(E2, "A");
519 const sf = comptime fieldInfo(S1, "a");
520 const uf = comptime fieldInfo(U1, "a");
512 const e1f = fieldInfo(E1, .A);
513 const e2f = fieldInfo(E2, .A);
514 const sf = fieldInfo(S1, .a);
515 const uf = fieldInfo(U1, .a);
521516
522517 testing.expect(mem.eql(u8, e1f.name, "A"));
523518 testing.expect(mem.eql(u8, e2f.name, "A"));
......@@ -568,6 +563,43 @@ test "std.meta.fieldNames" {
568563 testing.expectEqualSlices(u8, u1names[1], "b");
569564}
570565
566pub fn FieldEnum(comptime T: type) type {
567 const fieldInfos = fields(T);
568 var enumFields: [fieldInfos.len]std.builtin.TypeInfo.EnumField = undefined;
569 var decls = [_]std.builtin.TypeInfo.Declaration{};
570 inline for (fieldInfos) |field, i| {
571 enumFields[i] = .{
572 .name = field.name,
573 .value = i,
574 };
575 }
576 return @Type(.{
577 .Enum = .{
578 .layout = .Auto,
579 .tag_type = std.math.IntFittingRange(0, fieldInfos.len - 1),
580 .fields = &enumFields,
581 .decls = &decls,
582 .is_exhaustive = true,
583 },
584 });
585}
586
587fn expectEqualEnum(expected: anytype, actual: @TypeOf(expected)) void {
588 // TODO: https://github.com/ziglang/zig/issues/7419
589 // testing.expectEqual(@typeInfo(expected).Enum, @typeInfo(actual).Enum);
590 testing.expectEqual(@typeInfo(expected).Enum.layout, @typeInfo(actual).Enum.layout);
591 testing.expectEqual(@typeInfo(expected).Enum.tag_type, @typeInfo(actual).Enum.tag_type);
592 comptime testing.expectEqualSlices(std.builtin.TypeInfo.EnumField, @typeInfo(expected).Enum.fields, @typeInfo(actual).Enum.fields);
593 comptime testing.expectEqualSlices(std.builtin.TypeInfo.Declaration, @typeInfo(expected).Enum.decls, @typeInfo(actual).Enum.decls);
594 testing.expectEqual(@typeInfo(expected).Enum.is_exhaustive, @typeInfo(actual).Enum.is_exhaustive);
595}
596
597test "std.meta.FieldEnum" {
598 expectEqualEnum(enum { a }, FieldEnum(struct { a: u8 }));
599 expectEqualEnum(enum { a, b, c }, FieldEnum(struct { a: u8, b: void, c: f32 }));
600 expectEqualEnum(enum { a, b, c }, FieldEnum(union { a: u8, b: void, c: f32 }));
601}
602
571603pub fn TagType(comptime T: type) type {
572604 return switch (@typeInfo(T)) {
573605 .Enum => |info| info.tag_type,
lib/std/meta/trailer_flags.zig+2-18
......@@ -21,20 +21,7 @@ pub fn TrailerFlags(comptime Fields: type) type {
2121 pub const Int = meta.Int(.unsigned, bit_count);
2222 pub const bit_count = @typeInfo(Fields).Struct.fields.len;
2323
24 pub const FieldEnum = blk: {
25 comptime var fields: [bit_count]TypeInfo.EnumField = undefined;
26 inline for (@typeInfo(Fields).Struct.fields) |struct_field, i|
27 fields[i] = .{ .name = struct_field.name, .value = i };
28 break :blk @Type(.{
29 .Enum = .{
30 .layout = .Auto,
31 .tag_type = std.math.IntFittingRange(0, bit_count - 1),
32 .fields = &fields,
33 .decls = &[_]TypeInfo.Declaration{},
34 .is_exhaustive = true,
35 },
36 });
37 };
24 pub const FieldEnum = std.meta.FieldEnum(Fields);
3825
3926 pub const InitStruct = blk: {
4027 comptime var fields: [bit_count]TypeInfo.StructField = undefined;
......@@ -135,10 +122,7 @@ pub fn TrailerFlags(comptime Fields: type) type {
135122 }
136123
137124 pub fn Field(comptime field: FieldEnum) type {
138 inline for (@typeInfo(Fields).Struct.fields) |field_info, i| {
139 if (i == @enumToInt(field))
140 return field_info.field_type;
141 }
125 return @typeInfo(Fields).Struct.fields[@enumToInt(field)].field_type;
142126 }
143127
144128 pub fn sizeInBytes(self: Self) usize {
lib/std/zig/ast.zig+1-1
......@@ -688,7 +688,7 @@ pub const Node = struct {
688688
689689 /// Prefer `castTag` to this.
690690 pub fn cast(base: *Node, comptime T: type) ?*T {
691 if (std.meta.fieldInfo(T, "base").default_value) |default_base| {
691 if (std.meta.fieldInfo(T, .base).default_value) |default_base| {
692692 return base.castTag(default_base.tag);
693693 }
694694 inline for (@typeInfo(Tag).Enum.fields) |field| {
src/astgen.zig+7-7
......@@ -758,7 +758,7 @@ fn ptrSliceType(mod: *Module, scope: *Scope, src: usize, ptr_info: *ast.PtrInfo,
758758 }, child_type);
759759 }
760760
761 var kw_args: std.meta.fieldInfo(zir.Inst.PtrType, "kw_args").field_type = .{};
761 var kw_args: std.meta.fieldInfo(zir.Inst.PtrType, .kw_args).field_type = .{};
762762 kw_args.size = size;
763763 kw_args.@"allowzero" = ptr_info.allowzero_token != null;
764764 if (ptr_info.align_info) |some| {
......@@ -2756,8 +2756,8 @@ pub fn addZIRInstSpecial(
27562756 scope: *Scope,
27572757 src: usize,
27582758 comptime T: type,
2759 positionals: std.meta.fieldInfo(T, "positionals").field_type,
2760 kw_args: std.meta.fieldInfo(T, "kw_args").field_type,
2759 positionals: std.meta.fieldInfo(T, .positionals).field_type,
2760 kw_args: std.meta.fieldInfo(T, .kw_args).field_type,
27612761) !*T {
27622762 const gen_zir = scope.getGenZIR();
27632763 try gen_zir.instructions.ensureCapacity(mod.gpa, gen_zir.instructions.items.len + 1);
......@@ -2874,8 +2874,8 @@ pub fn addZIRInst(
28742874 scope: *Scope,
28752875 src: usize,
28762876 comptime T: type,
2877 positionals: std.meta.fieldInfo(T, "positionals").field_type,
2878 kw_args: std.meta.fieldInfo(T, "kw_args").field_type,
2877 positionals: std.meta.fieldInfo(T, .positionals).field_type,
2878 kw_args: std.meta.fieldInfo(T, .kw_args).field_type,
28792879) !*zir.Inst {
28802880 const inst_special = try addZIRInstSpecial(mod, scope, src, T, positionals, kw_args);
28812881 return &inst_special.base;
......@@ -2883,12 +2883,12 @@ pub fn addZIRInst(
28832883
28842884/// TODO The existence of this function is a workaround for a bug in stage1.
28852885pub fn addZIRInstConst(mod: *Module, scope: *Scope, src: usize, typed_value: TypedValue) !*zir.Inst {
2886 const P = std.meta.fieldInfo(zir.Inst.Const, "positionals").field_type;
2886 const P = std.meta.fieldInfo(zir.Inst.Const, .positionals).field_type;
28872887 return addZIRInst(mod, scope, src, zir.Inst.Const, P{ .typed_value = typed_value }, .{});
28882888}
28892889
28902890/// TODO The existence of this function is a workaround for a bug in stage1.
28912891pub fn addZIRInstLoop(mod: *Module, scope: *Scope, src: usize, body: zir.Module.Body) !*zir.Inst.Loop {
2892 const P = std.meta.fieldInfo(zir.Inst.Loop, "positionals").field_type;
2892 const P = std.meta.fieldInfo(zir.Inst.Loop, .positionals).field_type;
28932893 return addZIRInstSpecial(mod, scope, src, zir.Inst.Loop, P{ .body = body }, .{});
28942894}
src/ir.zig+1-1
......@@ -189,7 +189,7 @@ pub const Inst = struct {
189189 }
190190
191191 pub fn Args(comptime T: type) type {
192 return std.meta.fieldInfo(T, "args").field_type;
192 return std.meta.fieldInfo(T, .args).field_type;
193193 }
194194
195195 /// Returns `null` if runtime-known.
src/type.zig+1-1
......@@ -3232,7 +3232,7 @@ pub const Type = extern union {
32323232 }
32333233
32343234 pub fn Data(comptime t: Tag) type {
3235 return std.meta.fieldInfo(t.Type(), "data").field_type;
3235 return std.meta.fieldInfo(t.Type(), .data).field_type;
32363236 }
32373237 };
32383238
src/value.zig+1-1
......@@ -207,7 +207,7 @@ pub const Value = extern union {
207207 }
208208
209209 pub fn Data(comptime t: Tag) type {
210 return std.meta.fieldInfo(t.Type(), "data").field_type;
210 return std.meta.fieldInfo(t.Type(), .data).field_type;
211211 }
212212 };
213213