| author | |
| committer | |
| log | 8dfddf95fee5982d22512c0ac15278eabac5bcbb |
| tree | 0cd22c5bea3cb861971dc4820e59d8b41120e698 |
| parent | 3239f672d2aa61ad0fea0f400cd7917fa354ea0f |
Technically there is one valid use case for `fieldNames` which is use
with an enum or union so that those types can be used interchangeably.
But in practice these functions are mainly abused, because the callsites
always know what kind of type it is.
This commit encourages Zig users to embrace using `@typeInfo` directly
when doing type reflection.15 files changed, 41 insertions(+), 29 deletions(-)
lib/std/Build.zig+2-2| ... | ... | @@ -1109,7 +1109,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw |
| 1109 | 1109 | const type_id = comptime typeToEnum(T); |
| 1110 | 1110 | const enum_options = if (type_id == .@"enum" or type_id == .enum_list) blk: { |
| 1111 | 1111 | const EnumType = if (type_id == .enum_list) @typeInfo(T).pointer.child else T; |
| 1112 | const field_names = comptime std.meta.fieldNames(EnumType); | |
| 1112 | const field_names = @typeInfo(EnumType).@"enum".field_names; | |
| 1113 | 1113 | var options = std.array_list.Managed([]const u8).initCapacity(b.allocator, field_names.len) catch @panic("OOM"); |
| 1114 | 1114 | |
| 1115 | 1115 | inline for (field_names) |field_name| { |
| ... | ... | @@ -1420,7 +1420,7 @@ pub fn parseTargetQuery(options: std.Target.Query.ParseOptions) error{ParseFaile |
| 1420 | 1420 | \\available operating systems: |
| 1421 | 1421 | \\ |
| 1422 | 1422 | , .{diags.os_name.?}); |
| 1423 | inline for (comptime std.meta.fieldNames(Target.Os.Tag)) |field_name| { | |
| 1423 | inline for (@typeInfo(Target.Os.Tag).@"enum".field_names) |field_name| { | |
| 1424 | 1424 | std.debug.print(" {s}\n", .{field_name}); |
| 1425 | 1425 | } |
| 1426 | 1426 | return error.ParseFailed; |
lib/std/enums.zig+3-2| ... | ... | @@ -33,7 +33,8 @@ pub fn fromInt(comptime E: type, integer: anytype) ?E { |
| 33 | 33 | pub fn EnumFieldStruct(comptime E: type, comptime Data: type, comptime field_default: ?Data) type { |
| 34 | 34 | @setEvalBranchQuota(@typeInfo(E).@"enum".field_names.len + eval_branch_quota_cushion); |
| 35 | 35 | const default_ptr: ?*const anyopaque = if (field_default) |d| @ptrCast(&d) else null; |
| 36 | return @Struct(.auto, null, std.meta.fieldNames(E), &@splat(Data), &@splat(.{ .default_value_ptr = default_ptr })); | |
| 36 | const field_names = @typeInfo(E).@"enum".field_names; | |
| 37 | return @Struct(.auto, null, field_names, &@splat(Data), &@splat(.{ .default_value_ptr = default_ptr })); | |
| 37 | 38 | } |
| 38 | 39 | |
| 39 | 40 | /// Looks up the supplied field values in the given enum type. |
| ... | ... | @@ -454,7 +455,7 @@ pub fn EnumMap(comptime E: type, comptime V: type) type { |
| 454 | 455 | } |
| 455 | 456 | } |
| 456 | 457 | } else { |
| 457 | inline for (std.meta.fieldNames(E)) |field_name| { | |
| 458 | inline for (@typeInfo(E).@"enum".field_names) |field_name| { | |
| 458 | 459 | const key = @field(E, field_name); |
| 459 | 460 | if (@field(init_values, field_name)) |*v| { |
| 460 | 461 | const i = comptime Indexer.indexOf(key); |
lib/std/meta.zig+18-7| ... | ... | @@ -197,15 +197,17 @@ test containerLayout { |
| 197 | 197 | try testing.expect(containerLayout(U3) == .@"extern"); |
| 198 | 198 | } |
| 199 | 199 | |
| 200 | /// Instead of this function, prefer to use e.g. `@typeInfo(foo).@"struct".decl_names` | |
| 201 | /// directly when you know what kind of type it is. | |
| 200 | /// Returns the list of declaration names of namespace types. | |
| 201 | /// | |
| 202 | /// This function is only useful when the callsite does not know statically | |
| 203 | /// which kind of container it is. | |
| 202 | 204 | pub fn declarations(comptime T: type) []const [:0]const u8 { |
| 203 | 205 | return switch (@typeInfo(T)) { |
| 204 | 206 | .@"struct" => |info| info.decl_names, |
| 205 | 207 | .@"enum" => |info| info.decl_names, |
| 206 | 208 | .@"union" => |info| info.decl_names, |
| 207 | 209 | .@"opaque" => |info| info.decl_names, |
| 208 | else => @compileError("Expected struct, enum, union, or opaque type, found '" ++ @typeName(T) ++ "'"), | |
| 210 | else => comptime unreachable, // type lacks namespace | |
| 209 | 211 | }; |
| 210 | 212 | } |
| 211 | 213 | |
| ... | ... | @@ -241,10 +243,13 @@ test declarations { |
| 241 | 243 | } |
| 242 | 244 | |
| 243 | 245 | /// To be removed after Zig 0.17.0 is tagged. |
| 244 | pub const declarationInfo = @compileError("Deprecated; use '@hasDecl' instead"); | |
| 246 | pub const declarationInfo = @compileError("deprecated in favor of @hasDecl"); | |
| 245 | 247 | /// To be removed after Zig 0.17.0 is tagged. |
| 246 | pub const fields = @compileError("Deprecated; use 'fieldNames' and 'fieldTypes' instead"); | |
| 248 | pub const fields = @compileError("deprecated in favor of @typeInfo"); | |
| 247 | 249 | |
| 250 | /// Deprecated in favor of `@typeInfo`. | |
| 251 | /// | |
| 252 | /// To be removed after 0.17.0 is tagged. | |
| 248 | 253 | pub fn fieldInfo(comptime T: type, comptime field: FieldEnum(T)) switch (@typeInfo(T)) { |
| 249 | 254 | .@"struct" => struct { name: [:0]const u8, type: type, attrs: Type.Struct.FieldAttributes }, |
| 250 | 255 | .@"union" => struct { name: [:0]const u8, type: type, attrs: Type.Union.FieldAttributes }, |
| ... | ... | @@ -298,13 +303,16 @@ test fieldInfo { |
| 298 | 303 | try testing.expect(comptime uf.type == u8); |
| 299 | 304 | } |
| 300 | 305 | |
| 306 | /// Deprecated in favor of `@typeInfo`. | |
| 307 | /// | |
| 308 | /// To be removed after 0.17.0 is tagged. | |
| 301 | 309 | pub fn fieldNames(comptime T: type) []const [:0]const u8 { |
| 302 | 310 | return switch (@typeInfo(T)) { |
| 303 | 311 | .@"struct" => |s| s.field_names, |
| 304 | 312 | .@"union" => |u| u.field_names, |
| 305 | 313 | .@"enum" => |e| e.field_names, |
| 306 | 314 | .error_set => |es| es.error_names.?, |
| 307 | else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"), | |
| 315 | else => comptime unreachable, | |
| 308 | 316 | }; |
| 309 | 317 | } |
| 310 | 318 | |
| ... | ... | @@ -336,11 +344,14 @@ test fieldNames { |
| 336 | 344 | try testing.expectEqualSlices(u8, u1names[1], "b"); |
| 337 | 345 | } |
| 338 | 346 | |
| 347 | /// Deprecated in favor of `@typeInfo`. | |
| 348 | /// | |
| 349 | /// To be removed after 0.17.0 is tagged. | |
| 339 | 350 | pub fn fieldTypes(comptime T: type) []const type { |
| 340 | 351 | return switch (@typeInfo(T)) { |
| 341 | 352 | .@"struct" => |s| s.field_types, |
| 342 | 353 | .@"union" => |u| u.field_types, |
| 343 | else => @compileError("Expected struct or union type, found '" ++ @typeName(T) ++ "'"), | |
| 354 | else => comptime unreachable, | |
| 344 | 355 | }; |
| 345 | 356 | } |
| 346 | 357 |
lib/std/zig/AstGen.zig+2-2| ... | ... | @@ -74,13 +74,13 @@ src_hasher: std.zig.SrcHasher, |
| 74 | 74 | const InnerError = error{ OutOfMemory, AnalysisFail }; |
| 75 | 75 | |
| 76 | 76 | fn addExtra(astgen: *AstGen, extra: anytype) Allocator.Error!u32 { |
| 77 | const field_count = std.meta.fieldNames(@TypeOf(extra)).len; | |
| 77 | const field_count = @typeInfo(@TypeOf(extra)).@"struct".field_names.len; | |
| 78 | 78 | try astgen.extra.ensureUnusedCapacity(astgen.gpa, field_count); |
| 79 | 79 | return addExtraAssumeCapacity(astgen, extra); |
| 80 | 80 | } |
| 81 | 81 | |
| 82 | 82 | fn addExtraAssumeCapacity(astgen: *AstGen, extra: anytype) u32 { |
| 83 | const field_count = std.meta.fieldNames(@TypeOf(extra)).len; | |
| 83 | const field_count = @typeInfo(@TypeOf(extra)).@"struct".field_names.len; | |
| 84 | 84 | const extra_index: u32 = @intCast(astgen.extra.items.len); |
| 85 | 85 | astgen.extra.items.len += field_count; |
| 86 | 86 | setExtra(astgen, extra_index, extra); |
lib/std/zig/LibCInstallation.zig+1-1| ... | ... | @@ -43,7 +43,7 @@ pub const FindError = error{ |
| 43 | 43 | pub fn parse(allocator: Allocator, io: Io, libc_file: []const u8, target: *const std.Target) !LibCInstallation { |
| 44 | 44 | var self: LibCInstallation = .{}; |
| 45 | 45 | |
| 46 | const field_names = comptime std.meta.fieldNames(LibCInstallation); | |
| 46 | const field_names = @typeInfo(LibCInstallation).@"struct".field_names; | |
| 47 | 47 | const FoundKey = struct { |
| 48 | 48 | found: bool, |
| 49 | 49 | allocated: ?[]u8, |
lib/std/zig/llvm/Builder.zig+2-2| ... | ... | @@ -9517,7 +9517,7 @@ pub const Metadata = packed struct(u32) { |
| 9517 | 9517 | nodes: anytype, |
| 9518 | 9518 | w: *Writer, |
| 9519 | 9519 | ) !void { |
| 9520 | const names = comptime std.meta.fieldNames(@TypeOf(nodes)); | |
| 9520 | const names = @typeInfo(@TypeOf(nodes)).@"struct".field_names; | |
| 9521 | 9521 | |
| 9522 | 9522 | comptime var fmt_str: []const u8 = "{[distinct]s}{[node]s}("; |
| 9523 | 9523 | inline for (names) |name| fmt_str = fmt_str ++ "{[" ++ name ++ "]f}"; |
| ... | ... | @@ -13484,7 +13484,7 @@ fn metadataSimpleAssumeCapacity(self: *Builder, tag: Metadata.Tag, value: anytyp |
| 13484 | 13484 | builder: *const Builder, |
| 13485 | 13485 | pub fn hash(_: @This(), key: Key) u32 { |
| 13486 | 13486 | var hasher = std.hash.Wyhash.init(std.hash.int(@backingInt(key.tag))); |
| 13487 | inline for (comptime std.meta.fieldNames(@TypeOf(value))) |field_name| { | |
| 13487 | inline for (@typeInfo(@TypeOf(value)).@"struct".field_names) |field_name| { | |
| 13488 | 13488 | hasher.update(std.mem.asBytes(&@field(key.value, field_name))); |
| 13489 | 13489 | } |
| 13490 | 13490 | return @truncate(hasher.final()); |
lib/std/zig/llvm/bitcode_writer.zig+1-1| ... | ... | @@ -246,7 +246,7 @@ pub fn BitcodeWriter(comptime types: []const type) type { |
| 246 | 246 | |
| 247 | 247 | try self.bitcode.writeBits(comptime abbrevId(Abbrev), abbrev_len); |
| 248 | 248 | |
| 249 | const field_names = comptime std.meta.fieldNames(Abbrev); | |
| 249 | const field_names = @typeInfo(Abbrev).@"struct".field_names; | |
| 250 | 250 | |
| 251 | 251 | // This abbreviation might only contain literals |
| 252 | 252 | if (field_names.len == 0) return; |
lib/std/zig/system.zig+1-1| ... | ... | @@ -973,7 +973,7 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ |
| 973 | 973 | // relying on `builtin.target`. |
| 974 | 974 | const all_abis = comptime blk: { |
| 975 | 975 | assert(@backingInt(Target.Abi.none) == 0); |
| 976 | const field_names = std.meta.fieldNames(Target.Abi)[1..]; | |
| 976 | const field_names = @typeInfo(Target.Abi).@"enum".field_names[1..]; | |
| 977 | 977 | var array: [field_names.len]Target.Abi = undefined; |
| 978 | 978 | for (field_names, 0..) |field_name, i| { |
| 979 | 979 | array[i] = @field(Target.Abi, field_name); |
src/Air/Liveness.zig+3-3| ... | ... | @@ -351,7 +351,7 @@ const Analysis = struct { |
| 351 | 351 | extra: std.ArrayList(u32), |
| 352 | 352 | |
| 353 | 353 | fn addExtra(a: *Analysis, extra: anytype) Allocator.Error!u32 { |
| 354 | const field_count = std.meta.fieldNames(@TypeOf(extra)).len; | |
| 354 | const field_count = @typeInfo(@TypeOf(extra)).@"struct".field_names.len; | |
| 355 | 355 | try a.extra.ensureUnusedCapacity(a.gpa, field_count); |
| 356 | 356 | return addExtraAssumeCapacity(a, extra); |
| 357 | 357 | } |
| ... | ... | @@ -1012,7 +1012,7 @@ fn analyzeInstBlock( |
| 1012 | 1012 | const block_scope = data.block_scopes.get(inst).?; |
| 1013 | 1013 | const num_deaths = data.live_set.count() - block_scope.live_set.count(); |
| 1014 | 1014 | |
| 1015 | try a.extra.ensureUnusedCapacity(gpa, num_deaths + std.meta.fieldNames(Block).len); | |
| 1015 | try a.extra.ensureUnusedCapacity(gpa, num_deaths + @typeInfo(Block).@"struct".field_names.len); | |
| 1016 | 1016 | const extra_index = a.addExtraAssumeCapacity(Block{ |
| 1017 | 1017 | .death_count = num_deaths, |
| 1018 | 1018 | }); |
| ... | ... | @@ -1275,7 +1275,7 @@ fn analyzeInstCondBr( |
| 1275 | 1275 | // Write the mirrored deaths to `extra` |
| 1276 | 1276 | const then_death_count = @as(u32, @intCast(then_mirrored_deaths.items.len)); |
| 1277 | 1277 | const else_death_count = @as(u32, @intCast(else_mirrored_deaths.items.len)); |
| 1278 | try a.extra.ensureUnusedCapacity(gpa, std.meta.fieldNames(CondBr).len + then_death_count + else_death_count); | |
| 1278 | try a.extra.ensureUnusedCapacity(gpa, @typeInfo(CondBr).@"struct".field_names.len + then_death_count + else_death_count); | |
| 1279 | 1279 | const extra_index = a.addExtraAssumeCapacity(CondBr{ |
| 1280 | 1280 | .then_death_count = then_death_count, |
| 1281 | 1281 | .else_death_count = else_death_count, |
src/Sema.zig+1-1| ... | ... | @@ -34033,7 +34033,7 @@ pub fn getTmpAir(sema: Sema) Air { |
| 34033 | 34033 | } |
| 34034 | 34034 | |
| 34035 | 34035 | pub fn addExtra(sema: *Sema, extra: anytype) Allocator.Error!u32 { |
| 34036 | const field_count = std.meta.fieldNames(@TypeOf(extra)).len; | |
| 34036 | const field_count = @typeInfo(@TypeOf(extra)).@"struct".field_names.len; | |
| 34037 | 34037 | try sema.air_extra.ensureUnusedCapacity(sema.gpa, field_count); |
| 34038 | 34038 | return sema.addExtraAssumeCapacity(extra); |
| 34039 | 34039 | } |
src/codegen/riscv64/encoding.zig+1-1| ... | ... | @@ -498,7 +498,7 @@ pub const Instruction = union(Lir.Format) { |
| 498 | 498 | extra: u32, |
| 499 | 499 | |
| 500 | 500 | comptime { |
| 501 | for (std.meta.fieldTypes(Instruction)) |field_type| { | |
| 501 | for (@typeInfo(Instruction).@"union".field_types) |field_type| { | |
| 502 | 502 | assert(@bitSizeOf(field_type) == 32); |
| 503 | 503 | } |
| 504 | 504 | } |
src/codegen/wasm/CodeGen.zig+1-1| ... | ... | @@ -567,7 +567,7 @@ fn addCallIntrinsic(cg: *CodeGen, intrinsic: Mir.Intrinsic) error{OutOfMemory}!v |
| 567 | 567 | /// Appends entries to `mir_extra` based on the type of `extra`. |
| 568 | 568 | /// Returns the index into `mir_extra` |
| 569 | 569 | fn addExtra(cg: *CodeGen, extra: anytype) error{OutOfMemory}!u32 { |
| 570 | const field_count = std.meta.fieldNames(@TypeOf(extra)).len; | |
| 570 | const field_count = @typeInfo(@TypeOf(extra)).@"struct".field_names.len; | |
| 571 | 571 | try cg.mir_extra.ensureUnusedCapacity(cg.gpa, field_count); |
| 572 | 572 | return cg.addExtraAssumeCapacity(extra); |
| 573 | 573 | } |
src/codegen/x86_64/CodeGen.zig+1-1| ... | ... | @@ -1301,7 +1301,7 @@ fn addInst(self: *CodeGen, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index { |
| 1301 | 1301 | } |
| 1302 | 1302 | |
| 1303 | 1303 | fn addExtra(self: *CodeGen, extra: anytype) Allocator.Error!u32 { |
| 1304 | const field_count = std.meta.fieldNames(@TypeOf(extra)).len; | |
| 1304 | const field_count = @typeInfo(@TypeOf(extra)).@"struct".field_names.len; | |
| 1305 | 1305 | try self.mir_extra.ensureUnusedCapacity(self.gpa, field_count); |
| 1306 | 1306 | return self.addExtraAssumeCapacity(extra); |
| 1307 | 1307 | } |
src/link/Coff.zig+1-1| ... | ... | @@ -3654,7 +3654,7 @@ fn verifyParentSectionAttributes( |
| 3654 | 3654 | parent.name(coff).toSlice(coff), |
| 3655 | 3655 | }); |
| 3656 | 3656 | |
| 3657 | inline for (comptime std.meta.fieldNames(ObjectSectionAttributes)) |field| { | |
| 3657 | inline for (@typeInfo(ObjectSectionAttributes).@"struct".field_names) |field| { | |
| 3658 | 3658 | if (@field(child_attrs, field) != @field(parent_attrs, field)) { |
| 3659 | 3659 | err.addNote("flags.{s} was {d} in {s}, but {d} in {s}", .{ |
| 3660 | 3660 | field, |
src/print_targets.zig+3-3| ... | ... | @@ -43,9 +43,9 @@ pub fn cmdTargets( |
| 43 | 43 | { |
| 44 | 44 | var root_obj = try serializer.beginStruct(.{}); |
| 45 | 45 | |
| 46 | try root_obj.field("arch", meta.fieldNames(Target.Cpu.Arch), .{}); | |
| 47 | try root_obj.field("os", meta.fieldNames(Target.Os.Tag), .{}); | |
| 48 | try root_obj.field("abi", meta.fieldNames(Target.Abi), .{}); | |
| 46 | try root_obj.field("arch", @typeInfo(Target.Cpu.Arch).@"enum".field_names, .{}); | |
| 47 | try root_obj.field("os", @typeInfo(Target.Os.Tag).@"enum".field_names, .{}); | |
| 48 | try root_obj.field("abi", @typeInfo(Target.Abi).@"enum".field_names, .{}); | |
| 49 | 49 | |
| 50 | 50 | { |
| 51 | 51 | var libc_obj = try root_obj.beginTupleField("libc", .{}); |