Merge branch 'daurnimator-meta.fields'

closes #7420
This commit is contained in:
Andrew Kelley 2021-01-01 16:01:27 -07:00
commit 3dafc5b9a3
7 changed files with 56 additions and 40 deletions

View File

@ -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,

View File

@ -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 {

View File

@ -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| {

View File

@ -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 }, .{});
}

View File

@ -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.

View File

@ -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;
}
};

View File

@ -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;
}
};