Merge pull request 'Use struct-of-arrays style for std.lang.Type' (#35234) from Der_Teufel/zig:soa-builtin-type into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/35234
This commit is contained in:
mlugg
2026-05-28 09:45:54 +02:00
206 changed files with 2750 additions and 2488 deletions
+3 -3
View File
@@ -5752,7 +5752,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
{#header_open|@Fn#}
<pre>{#syntax#}@Fn(
comptime param_types: []const type,
comptime param_attrs: *const [param_types.len]std.lang.Type.Fn.Param.Attributes,
comptime param_attrs: *const [param_types.len]std.lang.Type.Fn.ParamAttributes,
comptime ReturnType: type,
comptime attrs: std.lang.Type.Fn.Attributes,
) type{#endsyntax#}</pre>
@@ -5765,7 +5765,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
comptime BackingInt: ?type,
comptime field_names: []const []const u8,
comptime field_types: *const [field_names.len]type,
comptime field_attrs: *const [field_names.len]std.lang.Type.StructField.Attributes,
comptime field_attrs: *const [field_names.len]std.lang.Type.Struct.FieldAttributes,
) type{#endsyntax#}</pre>
<p>Returns a {#link|struct#} type with the properties specified by the arguments.</p>
{#header_close#}
@@ -5777,7 +5777,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
comptime ArgType: ?type,
comptime field_names: []const []const u8,
comptime field_types: *const [field_names.len]type,
comptime field_attrs: *const [field_names.len]std.lang.Type.UnionField.Attributes,
comptime field_attrs: *const [field_names.len]std.lang.Type.Union.FieldAttributes,
) type{#endsyntax#}</pre>
<p>Returns a {#link|union#} type with the properties specified by the arguments.</p>
{#header_close#}
+2 -2
View File
@@ -1,7 +1,7 @@
fn isFieldOptional(comptime T: type, field_index: usize) !bool {
const fields = @typeInfo(T).@"struct".fields;
const field_types = @typeInfo(T).@"struct".field_types;
return switch (field_index) {
inline 0...fields.len - 1 => |idx| @typeInfo(fields[idx].type) == .optional,
inline 0...field_types.len - 1 => |idx| @typeInfo(field_types[idx]) == .optional,
else => return error.IndexOutOfBounds,
};
}
+2 -2
View File
@@ -102,8 +102,8 @@ test "std.meta.Tag" {
// @typeInfo tells us the field count and the fields names:
test "@typeInfo" {
try expectEqual(4, @typeInfo(Small).@"enum".fields.len);
try expectEqualStrings(@typeInfo(Small).@"enum".fields[1].name, "two");
try expectEqual(4, @typeInfo(Small).@"enum".field_names.len);
try expectEqualStrings(@typeInfo(Small).@"enum".field_names[1], "two");
}
// @tagName gives a [:0]const u8 representation of an enum value:
+1 -1
View File
@@ -3,7 +3,7 @@ const math = std.math;
const testing = std.testing;
test "fn reflection" {
try testing.expectEqual(bool, @typeInfo(@TypeOf(testing.expect)).@"fn".params[0].type.?);
try testing.expectEqual(bool, @typeInfo(@TypeOf(testing.expect)).@"fn".param_types[0].?);
try testing.expectEqual(testing.TmpDir, @typeInfo(@TypeOf(testing.tmpDir)).@"fn".return_type.?);
try testing.expect(@typeInfo(@TypeOf(math.Log2Int)).@"fn".is_generic);
+4 -3
View File
@@ -18,12 +18,13 @@ const AnySlice = union(enum) {
fn withFor(any: AnySlice) usize {
const Tag = @typeInfo(AnySlice).@"union".tag_type.?;
inline for (@typeInfo(Tag).@"enum".fields) |field| {
const info = @typeInfo(Tag).@"enum";
inline for (info.field_names, info.field_values) |field_name, field_value| {
// With `inline for` the function gets generated as
// a series of `if` statements relying on the optimizer
// to convert it to a switch.
if (field.value == @intFromEnum(any)) {
return @field(any, field.name).len;
if (field_value == @intFromEnum(any)) {
return @field(any, field_name).len;
}
}
// When using `inline for` the compiler doesn't know that every
+2 -2
View File
@@ -3,11 +3,11 @@ const expect = std.testing.expect;
const expectError = std.testing.expectError;
fn isFieldOptional(comptime T: type, field_index: usize) !bool {
const fields = @typeInfo(T).@"struct".fields;
const field_types = @typeInfo(T).@"struct".field_types;
return switch (field_index) {
// This prong is analyzed twice with `idx` being a
// comptime-known value each time.
inline 0, 1 => |idx| @typeInfo(fields[idx].type) == .optional,
inline 0, 1 => |idx| @typeInfo(field_types[idx]) == .optional,
else => return error.IndexOutOfBounds,
};
}
+1 -1
View File
@@ -3,7 +3,7 @@ const expectEqual = @import("std").testing.expectEqual;
var foo: u8 align(4) = 100;
test "global variable alignment" {
try expectEqual(4, @typeInfo(@TypeOf(&foo)).pointer.alignment);
try expectEqual(4, @typeInfo(@TypeOf(&foo)).pointer.attrs.@"align");
try expectEqual(*align(4) u8, @TypeOf(&foo));
const as_pointer_to_array: *align(4) [1]u8 = &foo;
const as_slice: []align(4) u8 = as_pointer_to_array;
+1 -1
View File
@@ -5,7 +5,7 @@ pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
test "variadic function" {
try testing.expectEqual(14, printf("Hello, world!\n"));
try testing.expect(@typeInfo(@TypeOf(printf)).@"fn".is_var_args);
try testing.expect(@typeInfo(@TypeOf(printf)).@"fn".attrs.varargs);
}
// test
+4 -3
View File
@@ -49,9 +49,10 @@ pub fn print(sc: *const ScannedConfig, w: *Writer) Writer.Error!void {
}
fn printStruct(sc: *const ScannedConfig, s: *Serializer.Struct, comptime S: type, v: S) !void {
inline for (@typeInfo(S).@"struct".fields) |field| {
try s.fieldPrefix(field.name);
try printValue(sc, s.container.serializer, field.type, @field(v, field.name));
const info = @typeInfo(S).@"struct";
inline for (info.field_names, info.field_types) |field_name, field_type| {
try s.fieldPrefix(field_name);
try printValue(sc, s.container.serializer, field_type, @field(v, field_name));
}
}
+2 -2
View File
@@ -113,8 +113,8 @@ fn checkCandidate(
}
fn supportedWindowsProgramExtension(ext: []const u8) bool {
inline for (@typeInfo(std.process.WindowsExtension).@"enum".fields) |field| {
if (std.ascii.eqlIgnoreCase(ext, "." ++ field.name)) return true;
inline for (@typeInfo(std.process.WindowsExtension).@"enum".field_names) |field_name| {
if (std.ascii.eqlIgnoreCase(ext, "." ++ field_name)) return true;
}
return false;
}
+3 -2
View File
@@ -87,8 +87,9 @@ pub fn init(cwd_path: []const u8) error{ OpenFrameworkFailed, MissingCoreService
errdefer core_services.close();
var resolved_symbols: ResolvedSymbols = undefined;
inline for (@typeInfo(ResolvedSymbols).@"struct".fields) |f| {
@field(resolved_symbols, f.name) = core_services.lookup(f.type, f.name) orelse return error.MissingCoreServicesSymbol;
const info = @typeInfo(ResolvedSymbols).@"struct";
inline for (info.field_names, info.field_types) |f_name, f_type| {
@field(resolved_symbols, f_name) = core_services.lookup(f_type, f_name) orelse return error.MissingCoreServicesSymbol;
}
return .{
+52 -51
View File
@@ -89,9 +89,9 @@ pub fn requiredArgCount(attr: Tag) u32 {
inline else => |tag| {
comptime var needed = 0;
comptime {
const fields = @typeInfo(@field(attributes, @tagName(tag))).@"struct".fields;
for (fields) |arg_field| {
if (!mem.eql(u8, arg_field.name, "__name_tok") and @typeInfo(arg_field.type) != .optional) needed += 1;
const info = @typeInfo(@field(attributes, @tagName(tag))).@"struct";
for (info.field_names, info.field_types) |arg_field_name, arg_field_type| {
if (!mem.eql(u8, arg_field_name, "__name_tok") and @typeInfo(arg_field_type) != .optional) needed += 1;
}
}
return needed;
@@ -105,9 +105,9 @@ pub fn maxArgCount(attr: Tag) u32 {
inline else => |tag| {
comptime var max = 0;
comptime {
const fields = @typeInfo(@field(attributes, @tagName(tag))).@"struct".fields;
for (fields) |arg_field| {
if (!mem.eql(u8, arg_field.name, "__name_tok")) max += 1;
const field_names = @typeInfo(@field(attributes, @tagName(tag))).@"struct".field_names;
for (field_names) |arg_field_name| {
if (!mem.eql(u8, arg_field_name, "__name_tok")) max += 1;
}
}
return max;
@@ -130,10 +130,10 @@ pub const Formatting = struct {
switch (attr) {
.calling_convention => unreachable,
inline else => |tag| {
const fields = @typeInfo(@field(attributes, @tagName(tag))).@"struct".fields;
const field_types = @typeInfo(@field(attributes, @tagName(tag))).@"struct".field_types;
if (fields.len == 0) unreachable;
const Unwrapped = UnwrapOptional(fields[0].type);
if (field_types.len == 0) unreachable;
const Unwrapped = UnwrapOptional(field_types[0]);
if (@typeInfo(Unwrapped) != .@"enum") unreachable;
return if (Unwrapped.opts.enum_kind == .identifier) "'" else "\"";
@@ -147,18 +147,18 @@ pub const Formatting = struct {
switch (attr) {
.calling_convention => unreachable,
inline else => |tag| {
const fields = @typeInfo(@field(attributes, @tagName(tag))).@"struct".fields;
const field_types = @typeInfo(@field(attributes, @tagName(tag))).@"struct".field_types;
if (fields.len == 0) unreachable;
const Unwrapped = UnwrapOptional(fields[0].type);
if (field_types.len == 0) unreachable;
const Unwrapped = UnwrapOptional(field_types[0]);
if (@typeInfo(Unwrapped) != .@"enum") unreachable;
const enum_fields = @typeInfo(Unwrapped).@"enum".fields;
const enum_field_names = @typeInfo(Unwrapped).@"enum".field_names;
const quote = comptime quoteChar(@enumFromInt(@intFromEnum(tag)));
comptime var values: []const u8 = quote ++ enum_fields[0].name ++ quote;
inline for (enum_fields[1..]) |enum_field| {
comptime var values: []const u8 = quote ++ enum_field_names[0] ++ quote;
inline for (enum_field_names[1..]) |enum_field_name| {
values = values ++ ", ";
values = values ++ quote ++ enum_field.name ++ quote;
values = values ++ quote ++ enum_field_name ++ quote;
}
return values;
},
@@ -171,10 +171,10 @@ pub fn wantsIdentEnum(attr: Tag) bool {
switch (attr) {
.calling_convention => return false,
inline else => |tag| {
const fields = @typeInfo(@field(attributes, @tagName(tag))).@"struct".fields;
const field_types = @typeInfo(@field(attributes, @tagName(tag))).@"struct".field_types;
if (fields.len == 0) return false;
const Unwrapped = UnwrapOptional(fields[0].type);
if (field_types.len == 0) return false;
const Unwrapped = UnwrapOptional(field_types[0]);
if (@typeInfo(Unwrapped) != .@"enum") return false;
return Unwrapped.opts.enum_kind == .identifier;
@@ -185,12 +185,12 @@ pub fn wantsIdentEnum(attr: Tag) bool {
pub fn diagnoseIdent(attr: Tag, arguments: *Arguments, ident: TokenIndex, p: *Parser) !bool {
switch (attr) {
inline else => |tag| {
const fields = @typeInfo(@field(attributes, @tagName(tag))).@"struct".fields;
if (fields.len == 0) unreachable;
const Unwrapped = UnwrapOptional(fields[0].type);
const info = @typeInfo(@field(attributes, @tagName(tag))).@"struct";
if (info.field_names.len == 0) unreachable;
const Unwrapped = UnwrapOptional(info.field_types[0]);
if (@typeInfo(Unwrapped) != .@"enum") unreachable;
if (std.meta.stringToEnum(Unwrapped, normalize(p.tokSlice(ident)))) |enum_val| {
@field(@field(arguments, @tagName(tag)), fields[0].name) = enum_val;
@field(@field(arguments, @tagName(tag)), info.field_names[0]) = enum_val;
return false;
}
@@ -203,11 +203,11 @@ pub fn diagnoseIdent(attr: Tag, arguments: *Arguments, ident: TokenIndex, p: *Pa
pub fn wantsAlignment(attr: Tag, idx: usize) bool {
switch (attr) {
inline else => |tag| {
const fields = @typeInfo(@field(attributes, @tagName(tag))).@"struct".fields;
if (fields.len == 0) return false;
const field_types = @typeInfo(@field(attributes, @tagName(tag))).@"struct".field_types;
if (field_types.len == 0) return false;
return switch (idx) {
inline 0...fields.len - 1 => |i| UnwrapOptional(fields[i].type) == Alignment,
inline 0...field_types.len - 1 => |i| UnwrapOptional(field_types[i]) == Alignment,
else => false,
};
},
@@ -217,12 +217,12 @@ pub fn wantsAlignment(attr: Tag, idx: usize) bool {
pub fn diagnoseAlignment(attr: Tag, arguments: *Arguments, arg_idx: u32, res: Parser.Result, arg_start: TokenIndex, p: *Parser) !bool {
switch (attr) {
inline else => |tag| {
const arg_fields = @typeInfo(@field(attributes, @tagName(tag))).@"struct".fields;
if (arg_fields.len == 0) unreachable;
const arg_info = @typeInfo(@field(attributes, @tagName(tag))).@"struct";
if (arg_info.field_names.len == 0) unreachable;
switch (arg_idx) {
inline 0...arg_fields.len - 1 => |arg_i| {
if (UnwrapOptional(arg_fields[arg_i].type) != Alignment) unreachable;
inline 0...arg_info.field_names.len - 1 => |arg_i| {
if (UnwrapOptional(arg_info.field_types[arg_i]) != Alignment) unreachable;
if (!res.val.is(.int, p.comp)) {
try p.err(arg_start, .alignas_unavailable, .{});
@@ -241,7 +241,7 @@ pub fn diagnoseAlignment(attr: Tag, arguments: *Arguments, arg_idx: u32, res: Pa
return true;
}
@field(@field(arguments, @tagName(tag)), arg_fields[arg_i].name) = .{ .requested = requested };
@field(@field(arguments, @tagName(tag)), arg_info.field_names[arg_i]) = .{ .requested = requested };
return false;
},
else => unreachable,
@@ -251,8 +251,8 @@ pub fn diagnoseAlignment(attr: Tag, arguments: *Arguments, arg_idx: u32, res: Pa
}
fn diagnoseField(
comptime decl: ZigType.Declaration,
comptime field: ZigType.StructField,
comptime decl_name: []const u8,
comptime field_name: []const u8,
comptime Wanted: type,
arguments: *Arguments,
res: Parser.Result,
@@ -283,7 +283,7 @@ fn diagnoseField(
if (res.val.opt_ref == .none) {
if (Wanted == Identifier and node == .decl_ref_expr) {
@field(@field(arguments, decl.name), field.name) = .{ .tok = node.decl_ref_expr.name_tok };
@field(@field(arguments, decl_name), field_name) = .{ .tok = node.decl_ref_expr.name_tok };
return false;
}
@@ -294,7 +294,7 @@ fn diagnoseField(
switch (key) {
.int => {
if (@typeInfo(Wanted) == .int) {
@field(@field(arguments, decl.name), field.name) = res.val.toInt(Wanted, p.comp) orelse {
@field(@field(arguments, decl_name), field_name) = res.val.toInt(Wanted, p.comp) orelse {
try p.err(arg_start, .attribute_int_out_of_range, .{res});
return true;
};
@@ -310,20 +310,20 @@ fn diagnoseField(
.char, .uchar, .schar => {},
else => break :validate,
}
@field(@field(arguments, decl.name), field.name) = try p.removeNull(res.val);
@field(@field(arguments, decl_name), field_name) = try p.removeNull(res.val);
return false;
}
try p.err(arg_start, .attribute_requires_string, .{decl.name});
try p.err(arg_start, .attribute_requires_string, .{decl_name});
return true;
} else if (@typeInfo(Wanted) == .@"enum" and @hasDecl(Wanted, "opts") and Wanted.opts.enum_kind == .string) {
const str = bytes[0 .. bytes.len - 1];
if (std.meta.stringToEnum(Wanted, str)) |enum_val| {
@field(@field(arguments, decl.name), field.name) = enum_val;
@field(@field(arguments, decl_name), field_name) = enum_val;
return false;
}
try p.err(arg_start, .unknown_attr_enum, .{ decl.name, Formatting.choices(@field(Tag, decl.name)) });
try p.err(arg_start, .unknown_attr_enum, .{ decl_name, Formatting.choices(@field(Tag, decl_name)) });
return true;
}
},
@@ -344,17 +344,18 @@ fn diagnoseField(
pub fn diagnose(attr: Tag, arguments: *Arguments, arg_idx: u32, res: Parser.Result, arg_start: TokenIndex, node: Tree.Node, p: *Parser) !bool {
switch (attr) {
inline else => |tag| {
const decl = @typeInfo(attributes).@"struct".decls[@intFromEnum(tag)];
const decl_name = @typeInfo(attributes).@"struct".decl_names[@intFromEnum(tag)];
const max_arg_count = comptime maxArgCount(tag);
if (arg_idx >= max_arg_count) {
try p.err(arg_start, .attribute_too_many_args, .{ @tagName(attr), max_arg_count });
return true;
}
const arg_fields = @typeInfo(@field(attributes, decl.name)).@"struct".fields;
const arg_field_names = @typeInfo(@field(attributes, decl_name)).@"struct".field_names;
const arg_field_types = @typeInfo(@field(attributes, decl_name)).@"struct".field_types;
switch (arg_idx) {
inline 0...arg_fields.len - 1 => |arg_i| {
return diagnoseField(decl, arg_fields[arg_i], UnwrapOptional(arg_fields[arg_i].type), arguments, res, arg_start, node, p);
inline 0...arg_field_names.len - 1 => |arg_i| {
return diagnoseField(decl_name, arg_field_names[arg_i], UnwrapOptional(arg_field_types[arg_i]), arguments, res, arg_start, node, p);
},
else => unreachable,
}
@@ -722,20 +723,20 @@ const attributes = struct {
pub const Tag = std.meta.DeclEnum(attributes);
pub const Arguments = blk: {
const decls = @typeInfo(attributes).@"struct".decls;
var names: [decls.len][]const u8 = undefined;
var types: [decls.len]type = undefined;
for (decls, &names, &types) |decl, *name, *T| {
name.* = decl.name;
T.* = @field(attributes, decl.name);
const decl_names = @typeInfo(attributes).@"struct".decl_names;
var names: [decl_names.len][]const u8 = undefined;
var types: [decl_names.len]type = undefined;
for (decl_names, &names, &types) |decl_name, *name, *T| {
name.* = decl_name;
T.* = @field(attributes, decl_name);
}
break :blk @Union(.auto, null, &names, &types, &@splat(.{}));
};
pub fn ArgumentsForTag(comptime tag: Tag) type {
const decl = @typeInfo(attributes).@"struct".decls[@intFromEnum(tag)];
return @field(attributes, decl.name);
const decl_name = @typeInfo(attributes).@"struct".decl_names[@intFromEnum(tag)];
return @field(attributes, decl_name);
}
pub fn initArguments(tag: Tag, name_tok: TokenIndex) Arguments {
+5 -5
View File
@@ -78,12 +78,12 @@ pub const Environment = struct {
pub fn loadAll(environ_map: *const std.process.Environ.Map) Environment {
var env: Environment = .{};
inline for (@typeInfo(@TypeOf(env)).@"struct".fields) |field| {
std.debug.assert(@field(env, field.name) == null);
inline for (@typeInfo(@TypeOf(env)).@"struct".field_names) |field_name| {
std.debug.assert(@field(env, field_name) == null);
var env_var_buf: [field.name.len]u8 = undefined;
const env_var_name = std.ascii.upperString(&env_var_buf, field.name);
@field(env, field.name) = environ_map.get(env_var_name);
var env_var_buf: [field_name.len]u8 = undefined;
const env_var_name = std.ascii.upperString(&env_var_buf, field_name);
@field(env, field_name) = environ_map.get(env_var_name);
}
return env;
}
+7 -7
View File
@@ -333,8 +333,8 @@ pub fn deinit(d: *Diagnostics) void {
/// Used by the __has_warning builtin macro.
pub fn warningExists(name: []const u8) bool {
if (std.mem.eql(u8, name, "pedantic")) return true;
inline for (comptime std.meta.declarations(Option)) |group| {
if (std.mem.eql(u8, name, group.name)) return true;
inline for (comptime std.meta.declarations(Option)) |group_name| {
if (std.mem.eql(u8, name, group_name)) return true;
}
return std.meta.stringToEnum(Option, name) != null;
}
@@ -349,9 +349,9 @@ pub fn set(d: *Diagnostics, name: []const u8, to: Message.Kind) Compilation.Erro
return;
}
inline for (comptime std.meta.declarations(Option)) |group| {
if (std.mem.eql(u8, name, group.name)) {
for (@field(Option, group.name)) |option| {
inline for (comptime std.meta.declarations(Option)) |group_name| {
if (std.mem.eql(u8, name, group_name)) {
for (@field(Option, group_name)) |option| {
d.state.options.put(option, to);
}
return;
@@ -494,8 +494,8 @@ pub fn addWithLocation(
pub fn formatArgs(w: *std.Io.Writer, fmt: []const u8, args: anytype) std.Io.Writer.Error!void {
var i: usize = 0;
inline for (std.meta.fields(@TypeOf(args))) |arg_info| {
const arg = @field(args, arg_info.name);
inline for (comptime std.meta.fieldNames(@TypeOf(args))) |arg_name| {
const arg = @field(args, arg_name);
i += switch (@TypeOf(arg)) {
[]const u8 => try formatString(w, fmt[i..], arg),
else => switch (@typeInfo(@TypeOf(arg))) {
+2 -2
View File
@@ -456,8 +456,8 @@ pub fn err(p: *Parser, tok_i: TokenIndex, diagnostic: Diagnostic, args: anytype)
fn formatArgs(p: *Parser, w: *std.Io.Writer, fmt: []const u8, args: anytype) !void {
var i: usize = 0;
inline for (std.meta.fields(@TypeOf(args))) |arg_info| {
const arg = @field(args, arg_info.name);
inline for (comptime std.meta.fieldNames(@TypeOf(args))) |arg_name| {
const arg = @field(args, arg_name);
i += switch (@TypeOf(arg)) {
[]const u8 => try Diagnostics.formatString(w, fmt[i..], arg),
Tree.Token.Id => try formatTokenId(w, fmt[i..], arg),
+11 -11
View File
@@ -3048,25 +3048,25 @@ fn dumpAttribute(tree: *const Tree, attr: Attribute, w: *std.Io.Writer) !void {
switch (attr.tag) {
inline else => |tag| {
const args = @field(attr.args, @tagName(tag));
const fields = @typeInfo(@TypeOf(args)).@"struct".fields;
if (fields.len == 0) {
const args_info = @typeInfo(@TypeOf(args)).@"struct";
if (args_info.field_names.len == 0) {
try w.writeByte('\n');
return;
}
try w.writeByte(' ');
inline for (fields, 0..) |f, i| {
if (comptime std.mem.eql(u8, f.name, "__name_tok")) continue;
inline for (args_info.field_names, args_info.field_types, 0..) |f_name, f_type, i| {
if (comptime std.mem.eql(u8, f_name, "__name_tok")) continue;
if (i != 0) {
try w.writeAll(", ");
}
try w.writeAll(f.name);
try w.writeAll(f_name);
try w.writeAll(": ");
switch (f.type) {
Interner.Ref => try w.print("\"{s}\"", .{tree.interner.get(@field(args, f.name)).bytes}),
?Interner.Ref => try w.print("\"{?s}\"", .{if (@field(args, f.name)) |str| tree.interner.get(str).bytes else null}),
else => switch (@typeInfo(f.type)) {
.@"enum" => try w.writeAll(@tagName(@field(args, f.name))),
else => try w.print("{any}", .{@field(args, f.name)}),
switch (f_type) {
Interner.Ref => try w.print("\"{s}\"", .{tree.interner.get(@field(args, f_name)).bytes}),
?Interner.Ref => try w.print("\"{?s}\"", .{if (@field(args, f_name)) |str| tree.interner.get(str).bytes else null}),
else => switch (@typeInfo(f_type)) {
.@"enum" => try w.writeAll(@tagName(@field(args, f_name))),
else => try w.print("{any}", .{@field(args, f_name)}),
},
}
}
+4 -4
View File
@@ -46,8 +46,8 @@ pub fn hasFeature(comp: *Compilation, ext: []const u8) bool {
.c_thread_local = comp.langopts.standard.atLeast(.c11) and comp.target.isTlsSupported(),
.bounds_attributes = comp.langopts.bounds_safety == .clang,
};
inline for (@typeInfo(@TypeOf(list)).@"struct".fields) |f| {
if (std.mem.eql(u8, f.name, ext)) return @field(list, f.name);
inline for (@typeInfo(@TypeOf(list)).@"struct".field_names) |f_name| {
if (std.mem.eql(u8, f_name, ext)) return @field(list, f_name);
}
return false;
}
@@ -70,8 +70,8 @@ pub fn hasExtension(comp: *Compilation, ext: []const u8) bool {
.matrix_types = false, // TODO
.matrix_types_scalar_division = false, // TODO
};
inline for (@typeInfo(@TypeOf(list)).@"struct".fields) |f| {
if (std.mem.eql(u8, f.name, ext)) return @field(list, f.name);
inline for (@typeInfo(@TypeOf(list)).@"struct".field_names) |f_name| {
if (std.mem.eql(u8, f_name, ext)) return @field(list, f_name);
}
return false;
}
+2 -2
View File
@@ -335,8 +335,8 @@ pub const Parser = struct {
fn formatArgs(w: *std.Io.Writer, fmt: []const u8, args: anytype) !void {
var i: usize = 0;
inline for (std.meta.fields(@TypeOf(args))) |arg_info| {
const arg = @field(args, arg_info.name);
inline for (comptime std.meta.fieldNames(@TypeOf(args))) |arg_name| {
const arg = @field(args, arg_name);
i += switch (@TypeOf(arg)) {
[]const u8 => try Diagnostics.formatString(w, fmt[i..], arg),
Ascii => try arg.format(w, fmt[i..]),
+14 -13
View File
@@ -733,7 +733,7 @@ pub fn put(i: *Interner, gpa: Allocator, key: Key) !Ref {
});
},
.record_ty => |elems| {
try i.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.Record).@"struct".fields.len +
try i.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.Record).@"struct".field_names.len +
elems.len);
i.items.appendAssumeCapacity(.{
.tag = .record_ty,
@@ -755,18 +755,19 @@ pub fn put(i: *Interner, gpa: Allocator, key: Key) !Ref {
}
fn addExtra(i: *Interner, gpa: Allocator, extra: anytype) Allocator.Error!u32 {
const fields = @typeInfo(@TypeOf(extra)).@"struct".fields;
try i.extra.ensureUnusedCapacity(gpa, fields.len);
const field_count = @typeInfo(@TypeOf(extra)).@"struct".field_names.len;
try i.extra.ensureUnusedCapacity(gpa, field_count);
return i.addExtraAssumeCapacity(extra);
}
fn addExtraAssumeCapacity(i: *Interner, extra: anytype) u32 {
const result = @as(u32, @intCast(i.extra.items.len));
inline for (@typeInfo(@TypeOf(extra)).@"struct".fields) |field| {
i.extra.appendAssumeCapacity(switch (field.type) {
Ref => @intFromEnum(@field(extra, field.name)),
u32 => @field(extra, field.name),
else => @compileError("bad field type: " ++ @typeName(field.type)),
const info = @typeInfo(@TypeOf(extra)).@"struct";
inline for (info.field_names, info.field_types) |field_name, field_type| {
i.extra.appendAssumeCapacity(switch (field_type) {
Ref => @intFromEnum(@field(extra, field_name)),
u32 => @field(extra, field_name),
else => @compileError("bad field type: " ++ @typeName(field_type)),
});
}
return result;
@@ -891,17 +892,17 @@ fn extraData(i: *const Interner, comptime T: type, index: usize) T {
fn extraDataTrail(i: *const Interner, comptime T: type, index: usize) struct { data: T, end: u32 } {
var result: T = undefined;
const fields = @typeInfo(T).@"struct".fields;
inline for (fields, 0..) |field, field_i| {
const info = @typeInfo(T).@"struct";
inline for (info.field_names, info.field_types, 0..) |field_name, field_type, field_i| {
const int32 = i.extra.items[field_i + index];
@field(result, field.name) = switch (field.type) {
@field(result, field_name) = switch (field_type) {
Ref => @enumFromInt(int32),
u32 => int32,
else => @compileError("bad field type: " ++ @typeName(field.type)),
else => @compileError("bad field type: " ++ @typeName(field_type)),
};
}
return .{
.data = result,
.end = @intCast(index + fields.len),
.end = @intCast(index + info.field_names.len),
};
}
+2 -2
View File
@@ -601,8 +601,8 @@ const Serialize = struct {
dest_module.* = try addModule(s, src_module);
}
comptime assert(std.mem.eql(u8, @typeInfo(Configuration.Module).@"struct".fields[2].name, "import_table"));
comptime assert(@typeInfo(Configuration.Module).@"struct".fields[2].type == Configuration.ImportTable.Index);
comptime assert(std.mem.eql(u8, @typeInfo(Configuration.Module).@"struct".field_names[2], "import_table"));
comptime assert(@typeInfo(Configuration.Module).@"struct".field_types[2] == Configuration.ImportTable.Index);
assert(wc.extra.items[@intFromEnum(module_index) + 2] == @intFromEnum(Configuration.ImportTable.Index.invalid));
const import_table_index = try wc.addDeduped(Configuration.ImportTable, .{
.imports = .{ .mal = imports },
+3 -2
View File
@@ -241,8 +241,9 @@ pub const Compression = enum(u32) {
};
fn structFieldsLittleToNative(comptime T: type, x: *T) void {
inline for (@typeInfo(T).@"struct".fields) |field| {
@field(x, field.name) = std.mem.littleToNative(field.type, @field(x, field.name));
const info = @typeInfo(T).@"struct";
inline for (info.field_names, info.field_types) |field_name, field_type| {
@field(x, field_name) = std.mem.littleToNative(field_type, @field(x, field_name));
}
}
+14 -12
View File
@@ -178,19 +178,20 @@ pub const UnsupportedCodePage = enum(u16) {
};
pub const CodePage = blk: {
const fields = @typeInfo(SupportedCodePage).@"enum".fields ++ @typeInfo(UnsupportedCodePage).@"enum".fields;
var field_names: [fields.len][]const u8 = undefined;
var field_values: [fields.len]u16 = undefined;
for (fields, &field_names, &field_values) |field, *name, *val| {
name.* = field.name;
val.* = field.value;
const field_names = @typeInfo(SupportedCodePage).@"enum".field_names ++ @typeInfo(UnsupportedCodePage).@"enum".field_names;
const field_values = @typeInfo(SupportedCodePage).@"enum".field_values ++ @typeInfo(UnsupportedCodePage).@"enum".field_values;
var cp_field_names: [field_names.len][]const u8 = undefined;
var cp_field_values: [field_names.len]u16 = undefined;
for (field_names, field_values, &cp_field_names, &cp_field_values) |field_name, field_value, *name, *val| {
name.* = field_name;
val.* = field_value;
}
break :blk @Enum(u16, .exhaustive, &field_names, &field_values);
break :blk @Enum(u16, .exhaustive, &cp_field_names, &cp_field_values);
};
pub fn isSupported(code_page: CodePage) bool {
inline for (@typeInfo(SupportedCodePage).@"enum".fields) |enumField| {
if (@intFromEnum(code_page) == @intFromEnum(@field(SupportedCodePage, enumField.name))) {
inline for (@typeInfo(SupportedCodePage).@"enum".field_names) |field_name| {
if (@intFromEnum(code_page) == @intFromEnum(@field(SupportedCodePage, field_name))) {
return true;
}
}
@@ -200,9 +201,10 @@ pub fn isSupported(code_page: CodePage) bool {
pub fn getByIdentifier(identifier: u16) !CodePage {
// There's probably a more efficient way to do this (e.g. ComptimeHashMap?) but
// this should be fine, especially since this function likely won't be called much.
inline for (@typeInfo(CodePage).@"enum".fields) |enumField| {
if (identifier == enumField.value) {
return @field(CodePage, enumField.name);
const info = @typeInfo(CodePage).@"enum";
inline for (info.field_names, info.field_values) |field_name, field_value| {
if (identifier == field_value) {
return @field(CodePage, field_name);
}
}
return error.InvalidCodePage;
+11 -10
View File
@@ -1054,17 +1054,18 @@ pub const supported_targets = struct {
.ebc,
};
comptime {
for (@typeInfo(Arch).@"enum".fields) |enum_field| {
_ = std.mem.indexOfScalar(Arch, ordered_for_display, @enumFromInt(enum_field.value)) orelse {
@compileError(std.fmt.comptimePrint("'{s}' missing from ordered_for_display", .{enum_field.name}));
const info = @typeInfo(Arch).@"enum";
for (info.field_names, info.field_values) |field_name, field_value| {
_ = std.mem.indexOfScalar(Arch, ordered_for_display, @enumFromInt(field_value)) orelse {
@compileError(std.fmt.comptimePrint("'{s}' missing from ordered_for_display", .{field_name}));
};
}
}
pub const longest_name = blk: {
var len = 0;
for (@typeInfo(Arch).@"enum".fields) |field| {
if (field.name.len > len) len = field.name.len;
for (@typeInfo(Arch).@"enum".field_names) |field_name| {
if (field_name.len > len) len = field_name.len;
}
break :blk len;
};
@@ -1106,14 +1107,14 @@ pub const supported_targets = struct {
// Enforce two things:
// 1. Arch enum field names are all lowercase (necessary for how fromStringIgnoreCase is implemented)
// 2. All enum fields in Arch have an associated RVA relocation type when converted to a coff.IMAGE.FILE.MACHINE
for (@typeInfo(Arch).@"enum".fields) |enum_field| {
const all_lower = all_lower: for (enum_field.name) |c| {
for (@typeInfo(Arch).@"enum".field_names) |field_name| {
const all_lower = all_lower: for (field_name) |c| {
if (std.ascii.isUpper(c)) break :all_lower false;
} else break :all_lower true;
if (!all_lower) @compileError(std.fmt.comptimePrint("Arch field is not all lowercase: {s}", .{enum_field.name}));
const coff_machine = @field(Arch, enum_field.name).toCoffMachineType();
if (!all_lower) @compileError(std.fmt.comptimePrint("Arch field is not all lowercase: {s}", .{field_name}));
const coff_machine = @field(Arch, field_name).toCoffMachineType();
_ = rvaRelocationTypeIndicator(coff_machine) orelse {
@compileError(std.fmt.comptimePrint("No RVA relocation for Arch: {s}", .{enum_field.name}));
@compileError(std.fmt.comptimePrint("No RVA relocation for Arch: {s}", .{field_name}));
};
}
}
+18 -22
View File
@@ -145,8 +145,8 @@ pub const ErrorDetails = struct {
comptime {
// all fields in the extra union should be 32 bits or less
for (std.meta.fields(Extra)) |field| {
std.debug.assert(@bitSizeOf(field.type) <= 32);
for (std.meta.fieldTypes(Extra)) |field_type| {
std.debug.assert(@bitSizeOf(field_type) <= 32);
}
}
@@ -257,18 +257,18 @@ pub const ErrorDetails = struct {
pub fn writeCommaSeparated(self: ExpectedTypes, writer: *std.Io.Writer) !void {
const struct_info = @typeInfo(ExpectedTypes).@"struct";
const num_real_fields = struct_info.fields.len - 1;
const num_real_fields = struct_info.field_names.len - 1;
const num_padding_bits = @bitSizeOf(ExpectedTypes) - num_real_fields;
const mask = std.math.maxInt(struct_info.backing_integer.?) >> num_padding_bits;
const relevant_bits_only = @as(struct_info.backing_integer.?, @bitCast(self)) & mask;
const num_set_bits = @popCount(relevant_bits_only);
var i: usize = 0;
inline for (struct_info.fields) |field_info| {
if (field_info.type != bool) continue;
inline for (struct_info.field_names, struct_info.field_types) |field_name, field_type| {
if (field_type != bool) continue;
if (i == num_set_bits) return;
if (@field(self, field_info.name)) {
try writer.writeAll(strings.get(field_info.name).?);
if (@field(self, field_name)) {
try writer.writeAll(strings.get(field_name).?);
i += 1;
if (num_set_bits > 2 and i != num_set_bits) {
try writer.writeAll(", ");
@@ -857,24 +857,20 @@ pub const ErrorDetails = struct {
/// Convenience struct only useful when the code page can be inferred from the token
pub const ErrorDetailsWithoutCodePage = blk: {
const details_info = @typeInfo(ErrorDetails);
const fields = details_info.@"struct".fields;
var field_names: [fields.len - 1][]const u8 = undefined;
var field_types: [fields.len - 1]type = undefined;
var field_attrs: [fields.len - 1]std.builtin.Type.StructField.Attributes = undefined;
const details_info = @typeInfo(ErrorDetails).@"struct";
const field_count = details_info.field_names.len;
var field_names: [field_count - 1][]const u8 = undefined;
var field_types: [field_count - 1]type = undefined;
var field_attrs: [field_count - 1]std.builtin.Type.Struct.FieldAttributes = undefined;
var i: usize = 0;
for (fields) |field| {
if (std.mem.eql(u8, field.name, "code_page")) continue;
field_names[i] = field.name;
field_types[i] = field.type;
field_attrs[i] = .{
.@"comptime" = field.is_comptime,
.@"align" = field.alignment,
.default_value_ptr = field.default_value_ptr,
};
for (details_info.field_names, details_info.field_types, details_info.field_attrs) |field_name, field_type, field_attr| {
if (std.mem.eql(u8, field_name, "code_page")) continue;
field_names[i] = field_name;
field_types[i] = field_type;
field_attrs[i] = field_attr;
i += 1;
}
std.debug.assert(i == fields.len - 1);
std.debug.assert(i == field_count - 1);
break :blk @Struct(.auto, null, &field_names, &field_types, &field_attrs);
};
+7 -7
View File
@@ -87,8 +87,8 @@ pub fn tagToId(tag: []const u8) error{InvalidLanguageTag}!?LanguageId {
if (parsed.multiple_suffixes) return null;
const longest_known_tag = comptime blk: {
var len = 0;
for (@typeInfo(LanguageId).@"enum".fields) |field| {
if (field.name.len > len) len = field.name.len;
for (@typeInfo(LanguageId).@"enum".field_names) |field_name| {
if (field_name.len > len) len = field_name.len;
}
break :blk len;
};
@@ -120,13 +120,13 @@ test tagToId {
test "exhaustive tagToId" {
@setEvalBranchQuota(2000);
inline for (@typeInfo(LanguageId).@"enum".fields) |field| {
const id = tagToId(field.name) catch |err| {
std.debug.print("tag: {s}\n", .{field.name});
inline for (@typeInfo(LanguageId).@"enum".field_names) |field_name| {
const id = tagToId(field_name) catch |err| {
std.debug.print("tag: {s}\n", .{field_name});
return err;
};
try std.testing.expectEqual(@field(LanguageId, field.name), id orelse {
std.debug.print("tag: {s}, got null\n", .{field.name});
try std.testing.expectEqual(@field(LanguageId, field_name), id orelse {
std.debug.print("tag: {s}, got null\n", .{field_name});
return error.TestExpectedEqual;
});
}
+1 -1
View File
@@ -137,7 +137,7 @@ pub const Parser = struct {
fn parseOptionalStatements(self: *Self, resource: ResourceType) ![]*Node {
var optional_statements: std.ArrayList(*Node) = .empty;
const num_statement_types = @typeInfo(rc.OptionalStatements).@"enum".fields.len;
const num_statement_types = @typeInfo(rc.OptionalStatements).@"enum".field_names.len;
var statement_type_has_duplicates: [num_statement_types]bool = @splat(false);
var last_statement_per_type: [num_statement_types]?*Node = @splat(null);
+6 -6
View File
@@ -925,18 +925,18 @@ const Context = struct {
}
fn addExtra(c: *Context, extra: anytype) Allocator.Error!std.zig.Ast.ExtraIndex {
const fields = std.meta.fields(@TypeOf(extra));
try c.extra_data.ensureUnusedCapacity(c.gpa, fields.len);
const info = @typeInfo(@TypeOf(extra)).@"struct";
try c.extra_data.ensureUnusedCapacity(c.gpa, info.field_names.len);
const result: std.zig.Ast.ExtraIndex = @enumFromInt(c.extra_data.items.len);
inline for (fields) |field| {
const data: u32 = switch (field.type) {
inline for (info.field_names, info.field_types) |field_name, field_type| {
const data: u32 = switch (field_type) {
NodeIndex,
std.zig.Ast.Node.OptionalIndex,
std.zig.Ast.OptionalTokenIndex,
std.zig.Ast.ExtraIndex,
=> @intFromEnum(@field(extra, field.name)),
=> @intFromEnum(@field(extra, field_name)),
TokenIndex,
=> @field(extra, field.name),
=> @field(extra, field_name),
else => @compileError("unexpected field type"),
};
c.extra_data.appendAssumeCapacity(data);
+3 -3
View File
@@ -170,11 +170,11 @@ pub fn ExtraData(comptime T: type) type {
}
pub fn extraData(doc: Document, comptime T: type, index: ExtraIndex) ExtraData(T) {
const fields = @typeInfo(T).@"struct".fields;
const info = @typeInfo(T).@"struct";
var i: usize = @intFromEnum(index);
var result: T = undefined;
inline for (fields) |field| {
@field(result, field.name) = switch (field.type) {
inline for (info.field_names, info.field_types) |field_name, field_type| {
@field(result, field_name) = switch (field_type) {
u32 => doc.extra[i],
else => @compileError("bad field type"),
};
+3 -3
View File
@@ -1574,11 +1574,11 @@ fn parseInlines(p: *Parser, content: []const u8) !ExtraIndex {
}
pub fn extraData(p: Parser, comptime T: type, index: ExtraIndex) ExtraData(T) {
const fields = @typeInfo(T).@"struct".fields;
const info = @typeInfo(T).@"struct";
var i: usize = @intFromEnum(index);
var result: T = undefined;
inline for (fields) |field| {
@field(result, field.name) = switch (field.type) {
inline for (info.field_names, info.field_types) |field_name, field_type| {
@field(result, field_name) = switch (field_type) {
u32 => p.extra.items[i],
else => @compileError("bad field type"),
};
+52 -53
View File
@@ -389,9 +389,10 @@ fn createChild(
fn userInputOptionsFromArgs(arena: Allocator, args: anytype) UserInputOptionsMap {
var map = UserInputOptionsMap.init(arena);
inline for (@typeInfo(@TypeOf(args)).@"struct".fields) |field| {
if (field.type == @TypeOf(null)) continue;
addUserInputOptionFromArg(arena, &map, field, field.type, @field(args, field.name));
const args_info = @typeInfo(@TypeOf(args)).@"struct";
inline for (args_info.field_names, args_info.field_types) |field_name, field_type| {
if (field_type == @TypeOf(null)) continue;
addUserInputOptionFromArg(arena, &map, field_name, field_type, @field(args, field_name));
}
return map;
}
@@ -399,15 +400,15 @@ fn userInputOptionsFromArgs(arena: Allocator, args: anytype) UserInputOptionsMap
fn addUserInputOptionFromArg(
arena: Allocator,
map: *UserInputOptionsMap,
field: std.builtin.Type.StructField,
field_name: [:0]const u8,
comptime T: type,
/// If null, the value won't be added, but `T` will still be type-checked.
maybe_value: ?T,
) void {
switch (T) {
Target.Query => return if (maybe_value) |v| {
map.put(field.name, .{
.name = field.name,
map.put(field_name, .{
.name = field_name,
.value = .{ .scalar = v.zigTriple(arena) catch @panic("OOM") },
.used = false,
}) catch @panic("OOM");
@@ -418,8 +419,8 @@ fn addUserInputOptionFromArg(
}) catch @panic("OOM");
},
ResolvedTarget => return if (maybe_value) |v| {
map.put(field.name, .{
.name = field.name,
map.put(field_name, .{
.name = field_name,
.value = .{ .scalar = v.query.zigTriple(arena) catch @panic("OOM") },
.used = false,
}) catch @panic("OOM");
@@ -430,15 +431,15 @@ fn addUserInputOptionFromArg(
}) catch @panic("OOM");
},
std.zig.BuildId => return if (maybe_value) |v| {
map.put(field.name, .{
.name = field.name,
map.put(field_name, .{
.name = field_name,
.value = .{ .scalar = std.fmt.allocPrint(arena, "{f}", .{v}) catch @panic("OOM") },
.used = false,
}) catch @panic("OOM");
},
LazyPath => return if (maybe_value) |v| {
map.put(field.name, .{
.name = field.name,
map.put(field_name, .{
.name = field_name,
.value = .{ .lazy_path = v.dupeInner(arena) },
.used = false,
}) catch @panic("OOM");
@@ -446,15 +447,15 @@ fn addUserInputOptionFromArg(
[]const LazyPath => return if (maybe_value) |v| {
var list = std.array_list.Managed(LazyPath).initCapacity(arena, v.len) catch @panic("OOM");
for (v) |lp| list.appendAssumeCapacity(lp.dupeInner(arena));
map.put(field.name, .{
.name = field.name,
map.put(field_name, .{
.name = field_name,
.value = .{ .lazy_path_list = list },
.used = false,
}) catch @panic("OOM");
},
[]const u8 => return if (maybe_value) |v| {
map.put(field.name, .{
.name = field.name,
map.put(field_name, .{
.name = field_name,
.value = .{ .scalar = arena.dupe(u8, v) catch @panic("OOM") },
.used = false,
}) catch @panic("OOM");
@@ -462,37 +463,37 @@ fn addUserInputOptionFromArg(
[]const []const u8 => return if (maybe_value) |v| {
var list = std.array_list.Managed([]const u8).initCapacity(arena, v.len) catch @panic("OOM");
for (v) |s| list.appendAssumeCapacity(arena.dupe(u8, s) catch @panic("OOM"));
map.put(field.name, .{
.name = field.name,
map.put(field_name, .{
.name = field_name,
.value = .{ .list = list },
.used = false,
}) catch @panic("OOM");
},
else => switch (@typeInfo(T)) {
.bool => return if (maybe_value) |v| {
map.put(field.name, .{
.name = field.name,
map.put(field_name, .{
.name = field_name,
.value = .{ .scalar = if (v) "true" else "false" },
.used = false,
}) catch @panic("OOM");
},
.@"enum", .enum_literal => return if (maybe_value) |v| {
map.put(field.name, .{
.name = field.name,
map.put(field_name, .{
.name = field_name,
.value = .{ .scalar = @tagName(v) },
.used = false,
}) catch @panic("OOM");
},
.comptime_int, .int => return if (maybe_value) |v| {
map.put(field.name, .{
.name = field.name,
map.put(field_name, .{
.name = field_name,
.value = .{ .scalar = std.fmt.allocPrint(arena, "{d}", .{v}) catch @panic("OOM") },
.used = false,
}) catch @panic("OOM");
},
.comptime_float, .float => return if (maybe_value) |v| {
map.put(field.name, .{
.name = field.name,
map.put(field_name, .{
.name = field_name,
.value = .{ .scalar = std.fmt.allocPrint(arena, "{x}", .{v}) catch @panic("OOM") },
.used = false,
}) catch @panic("OOM");
@@ -503,7 +504,7 @@ fn addUserInputOptionFromArg(
addUserInputOptionFromArg(
arena,
map,
field,
field_name,
@Pointer(.slice, .{ .@"const" = true }, array_info.child, null),
maybe_value orelse null,
);
@@ -515,8 +516,8 @@ fn addUserInputOptionFromArg(
.@"enum" => return if (maybe_value) |v| {
var list = std.array_list.Managed([]const u8).initCapacity(arena, v.len) catch @panic("OOM");
for (v) |tag| list.appendAssumeCapacity(@tagName(tag));
map.put(field.name, .{
.name = field.name,
map.put(field_name, .{
.name = field_name,
.value = .{ .list = list },
.used = false,
}) catch @panic("OOM");
@@ -525,7 +526,7 @@ fn addUserInputOptionFromArg(
addUserInputOptionFromArg(
arena,
map,
field,
field_name,
@Pointer(ptr_info.size, .{ .@"const" = true }, ptr_info.child, null),
maybe_value orelse null,
);
@@ -541,7 +542,7 @@ fn addUserInputOptionFromArg(
addUserInputOptionFromArg(
arena,
map,
field,
field_name,
info.child,
maybe_value orelse null,
);
@@ -551,7 +552,7 @@ fn addUserInputOptionFromArg(
else => {},
},
}
@compileError("option '" ++ field.name ++ "' has unsupported type: " ++ @typeName(field.type));
@compileError("option '" ++ field_name ++ "' has unsupported type: " ++ @typeName(T));
}
const OrderedUserValue = union(enum) {
@@ -1114,11 +1115,11 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw
const type_id = comptime typeToEnum(T);
const enum_options = if (type_id == .@"enum" or type_id == .enum_list) blk: {
const EnumType = if (type_id == .enum_list) @typeInfo(T).pointer.child else T;
const fields = comptime std.meta.fields(EnumType);
var options = std.array_list.Managed([]const u8).initCapacity(arena, fields.len) catch @panic("OOM");
const field_names = comptime std.meta.fieldNames(EnumType);
var options = std.array_list.Managed([]const u8).initCapacity(b.allocator, field_names.len) catch @panic("OOM");
inline for (fields) |field| {
options.appendAssumeCapacity(field.name);
inline for (field_names) |field_name| {
options.appendAssumeCapacity(field_name);
}
break :blk options.toOwnedSlice() catch @panic("OOM");
@@ -1407,8 +1408,8 @@ pub fn parseTargetQuery(options: std.Target.Query.ParseOptions) error{ParseFaile
\\available operating systems:
\\
, .{diags.os_name.?});
inline for (std.meta.fields(Target.Os.Tag)) |field| {
std.debug.print(" {s}\n", .{field.name});
inline for (comptime std.meta.fieldNames(Target.Os.Tag)) |field_name| {
std.debug.print(" {s}\n", .{field_name});
}
return error.ParseFailed;
},
@@ -1811,8 +1812,8 @@ pub fn findProgram(b: *Build, options: FindProgramOptions) ?[]const u8 {
}
fn supportedWindowsProgramExtension(ext: []const u8) bool {
inline for (@typeInfo(std.process.WindowsExtension).@"enum".fields) |field| {
if (std.ascii.eqlIgnoreCase(ext, "." ++ field.name)) return true;
inline for (@typeInfo(std.process.WindowsExtension).@"enum".field_names) |field_name| {
if (std.ascii.eqlIgnoreCase(ext, "." ++ field_name)) return true;
}
return false;
}
@@ -2072,8 +2073,7 @@ inline fn findImportPkgHashOrFatal(b: *Build, comptime asking_build_zig: type, c
const deps = build_runner.dependencies;
const arena = b.graph.arena;
const b_pkg_hash, const b_pkg_deps = comptime for (@typeInfo(deps.packages).@"struct".decls) |decl| {
const pkg_hash = decl.name;
const b_pkg_hash, const b_pkg_deps = comptime for (@typeInfo(deps.packages).@"struct".decl_names) |pkg_hash| {
const pkg = @field(deps.packages, pkg_hash);
if (@hasDecl(pkg, "build_zig") and pkg.build_zig == asking_build_zig) break .{ pkg_hash, pkg.deps };
} else .{ "", deps.root_deps };
@@ -2116,9 +2116,9 @@ pub fn lazyDependency(b: *Build, name: []const u8, args: anytype) ?*Dependency {
const deps = build_runner.dependencies;
const pkg_hash = findPkgHashOrFatal(b, name);
inline for (@typeInfo(deps.packages).@"struct".decls) |decl| {
if (mem.eql(u8, decl.name, pkg_hash)) {
const pkg = @field(deps.packages, decl.name);
inline for (@typeInfo(deps.packages).@"struct".decl_names) |decl_name| {
if (mem.eql(u8, decl_name, pkg_hash)) {
const pkg = @field(deps.packages, decl_name);
const available = !@hasDecl(pkg, "available") or pkg.available;
if (!available) {
markNeededLazyDep(b, pkg_hash);
@@ -2136,9 +2136,9 @@ pub fn dependency(b: *Build, name: []const u8, args: anytype) *Dependency {
const deps = build_runner.dependencies;
const pkg_hash = findPkgHashOrFatal(b, name);
inline for (@typeInfo(deps.packages).@"struct".decls) |decl| {
if (mem.eql(u8, decl.name, pkg_hash)) {
const pkg = @field(deps.packages, decl.name);
inline for (@typeInfo(deps.packages).@"struct".decl_names) |decl_name| {
if (mem.eql(u8, decl_name, pkg_hash)) {
const pkg = @field(deps.packages, decl_name);
if (@hasDecl(pkg, "available")) {
panic("dependency '{s}{s}' is marked as lazy in build.zig.zon which means it must use the lazyDependency function instead", .{ b.dep_prefix, name });
}
@@ -2166,9 +2166,9 @@ pub inline fn lazyImport(
const deps = build_runner.dependencies;
const pkg_hash = findImportPkgHashOrFatal(b, asking_build_zig, dep_name);
inline for (@typeInfo(deps.packages).@"struct".decls) |decl| {
if (comptime mem.eql(u8, decl.name, pkg_hash)) {
const pkg = @field(deps.packages, decl.name);
inline for (@typeInfo(deps.packages).@"struct".decl_names) |decl_name| {
if (comptime mem.eql(u8, decl_name, pkg_hash)) {
const pkg = @field(deps.packages, decl_name);
const available = !@hasDecl(pkg, "available") or pkg.available;
if (!available) {
markNeededLazyDep(b, pkg_hash);
@@ -2197,8 +2197,7 @@ pub fn dependencyFromBuildZig(
const arena = graph.arena;
find_dep: {
const pkg, const pkg_hash = inline for (@typeInfo(deps.packages).@"struct".decls) |decl| {
const pkg_hash = decl.name;
const pkg, const pkg_hash = inline for (@typeInfo(deps.packages).@"struct".decl_names) |pkg_hash| {
const pkg = @field(deps.packages, pkg_hash);
if (@hasDecl(pkg, "build_zig") and pkg.build_zig == build_zig) break .{ pkg, pkg_hash };
} else break :find_dep;
+2 -2
View File
@@ -1241,7 +1241,7 @@ pub const Manifest = struct {
}
pub fn populateFileSystemInputs(man: *Manifest, buf: *std.ArrayList(u8)) Allocator.Error!void {
assert(@typeInfo(std.zig.Server.Message.PathPrefix).@"enum".fields.len == man.cache.prefixes_len);
assert(@typeInfo(std.zig.Server.Message.PathPrefix).@"enum".field_names.len == man.cache.prefixes_len);
buf.clearRetainingCapacity();
const gpa = man.cache.gpa;
const files = man.files.keys();
@@ -1259,7 +1259,7 @@ pub const Manifest = struct {
pub fn populateOtherManifest(man: *Manifest, other: *Manifest, prefix_map: [4]u8) Allocator.Error!void {
const gpa = other.cache.gpa;
assert(@typeInfo(std.zig.Server.Message.PathPrefix).@"enum".fields.len == man.cache.prefixes_len);
assert(@typeInfo(std.zig.Server.Message.PathPrefix).@"enum".field_names.len == man.cache.prefixes_len);
assert(man.cache.prefixes_len == 4);
for (man.files.keys()) |file| {
const prefixed_path: PrefixedPath = .{
+19 -16
View File
@@ -2884,7 +2884,10 @@ pub const Storage = enum {
}
pub fn cast(this: @This(), c: *const Configuration, comptime S: type) ?S {
const wanted_tag = @typeInfo(S.Flags).@"struct".fields[0].defaultValue().?;
const wanted_tag = blk: {
const info = @typeInfo(S.Flags).@"struct";
break :blk info.field_attrs[0].defaultValue(info.field_types[0]).?;
};
const base_flags: BaseFlags = @bitCast(c.extra[@intFromEnum(this)]);
if (base_flags.tag != wanted_tag) return null;
var i: usize = @intFromEnum(this);
@@ -3047,8 +3050,8 @@ pub const Storage = enum {
switch (@typeInfo(T)) {
.@"struct" => |info| {
var result: T = undefined;
inline for (info.fields) |field| {
@field(result, field.name) = dataField(buffer, i, &result, field.type);
inline for (info.field_names, info.field_types) |field_name, field_type| {
@field(result, field_name) = dataField(buffer, i, &result, field_type);
}
return result;
},
@@ -3058,7 +3061,7 @@ pub const Storage = enum {
inline else => |comptime_tag| @unionInit(
T,
@tagName(comptime_tag),
data(buffer, i, info.fields[@intFromEnum(comptime_tag)].type),
data(buffer, i, info.field_types[@intFromEnum(comptime_tag)]),
),
};
},
@@ -3125,7 +3128,7 @@ pub const Storage = enum {
buffer,
i,
container,
@typeInfo(Field.Union).@"union".fields[@intFromEnum(comptime_tag)].type,
@typeInfo(Field.Union).@"union".field_types[@intFromEnum(comptime_tag)],
),
),
},
@@ -3167,7 +3170,7 @@ pub const Storage = enum {
.multi_list => {
const data_start = i.* + 1;
const len = buffer[data_start - 1];
defer i.* = data_start + len * @typeInfo(Field.Elem).@"struct".fields.len;
defer i.* = data_start + len * @typeInfo(Field.Elem).@"struct".field_names.len;
return .{ .mal = .{
.bytes = @ptrCast(@constCast(buffer[data_start..][0..len])),
.len = len,
@@ -3205,10 +3208,10 @@ pub const Storage = enum {
/// Returns new end index.
fn setExtra(buffer: []u32, index: usize, extra: anytype) usize {
const fields = @typeInfo(@TypeOf(extra)).@"struct".fields;
const info = @typeInfo(@TypeOf(extra)).@"struct";
var i = index;
inline for (fields) |field| {
i += setExtraField(buffer, i, field.type, @field(extra, field.name));
inline for (info.field_names, info.field_types) |field_name, field_type| {
i += setExtraField(buffer, i, field_type, @field(extra, field_name));
}
return i;
}
@@ -3236,7 +3239,7 @@ pub const Storage = enum {
.flag_length_prefixed_list,
.flag_list,
=> 1 + @divExact(@sizeOf(Field.Elem), @sizeOf(u32)) * field.slice.len,
.multi_list => 1 + field.mal.len * @typeInfo(Field.Elem).@"struct".fields.len,
.multi_list => 1 + field.mal.len * @typeInfo(Field.Elem).@"struct".field_names.len,
.union_list => Field.extraLen(field.len),
.flag_union => switch (field.u) {
inline else => |v| extraFieldLen(v),
@@ -3249,10 +3252,10 @@ pub const Storage = enum {
}
fn extraLen(extra: anytype) usize {
const fields = @typeInfo(@TypeOf(extra)).@"struct".fields;
const field_names = @typeInfo(@TypeOf(extra)).@"struct".field_names;
var i: usize = 0;
inline for (fields) |field| {
i += Storage.extraFieldLen(@field(extra, field.name));
inline for (field_names) |name| {
i += Storage.extraFieldLen(@field(extra, name));
}
return i;
}
@@ -3324,12 +3327,12 @@ pub const Storage = enum {
.multi_list => {
const len: u32 = @intCast(value.mal.len);
buffer[i] = len;
const fields = @typeInfo(Field.Elem).@"struct".fields;
inline for (0..fields.len) |field_i| @memcpy(
const field_names = @typeInfo(Field.Elem).@"struct".field_names;
inline for (0..field_names.len) |field_i| @memcpy(
buffer[i + 1 + field_i * len ..][0..len],
@as([]const u32, @ptrCast(value.mal.items(@enumFromInt(field_i)))),
);
return 1 + fields.len * len;
return 1 + field_names.len * len;
},
.union_list => {
if (value.len == 0) return 0;
+3 -2
View File
@@ -173,8 +173,9 @@ fn addValueInner(config_header: *ConfigHeader, name: []const u8, comptime T: typ
}
pub fn addValues(config_header: *ConfigHeader, values: anytype) void {
inline for (@typeInfo(@TypeOf(values)).@"struct".fields) |field| {
addValue(config_header, field.name, field.type, @field(values, field.name));
const info = @typeInfo(@TypeOf(values)).@"struct";
inline for (info.field_names, info.field_types) |field_name, field_type| {
addValue(config_header, field_name, field_type, @field(values, field_name));
}
}
+28 -22
View File
@@ -299,14 +299,14 @@ fn printEnum(
try out.appendNTimes(gpa, ' ', indent);
try out.print(gpa, "pub const {f} = enum ({s}) {{\n", .{ std.zig.fmtId(@typeName(T)), @typeName(val.tag_type) });
inline for (val.fields) |field| {
inline for (val.field_names, val.field_values) |field_name, field_value| {
try out.appendNTimes(gpa, ' ', indent);
try out.print(gpa, " {f} = {d},\n", .{
std.zig.fmtIdFlags(field.name, .{ .allow_primitive = true }), field.value,
std.zig.fmtIdFlags(field_name, .{ .allow_primitive = true }), field_value,
});
}
if (!val.is_exhaustive) {
if (val.mode == .nonexhaustive) {
try out.appendNTimes(gpa, ' ', indent);
try out.appendSlice(gpa, " _,\n");
}
@@ -315,7 +315,13 @@ fn printEnum(
try out.appendSlice(gpa, "};\n");
}
fn printStruct(options: *Options, out: *std.ArrayList(u8), comptime T: type, comptime val: std.builtin.Type.Struct, indent: u8) !void {
fn printStruct(
options: *Options,
out: *std.ArrayList(u8),
comptime T: type,
comptime val: std.builtin.Type.Struct,
indent: u8,
) !void {
const gpa = options.step.owner.allocator;
const gop = try options.encountered_types.getOrPut(gpa, @typeName(T));
if (gop.found_existing) return;
@@ -331,32 +337,32 @@ fn printStruct(options: *Options, out: *std.ArrayList(u8), comptime T: type, com
try out.appendSlice(gpa, " {\n");
inline for (val.fields) |field| {
inline for (val.field_names, val.field_types, val.field_attrs) |field_name, field_type, field_attrs| {
try out.appendNTimes(gpa, ' ', indent);
const type_name = @typeName(field.type);
const type_name = @typeName(field_type);
// If the type name doesn't contains a '.' the type is from zig builtins.
if (std.mem.containsAtLeast(u8, type_name, 1, ".")) {
try out.print(gpa, " {f}: {f}", .{
std.zig.fmtIdFlags(field.name, .{ .allow_underscore = true, .allow_primitive = true }),
std.zig.fmtIdFlags(field_name, .{ .allow_underscore = true, .allow_primitive = true }),
std.zig.fmtId(type_name),
});
} else {
try out.print(gpa, " {f}: {s}", .{
std.zig.fmtIdFlags(field.name, .{ .allow_underscore = true, .allow_primitive = true }),
std.zig.fmtIdFlags(field_name, .{ .allow_underscore = true, .allow_primitive = true }),
type_name,
});
}
if (field.defaultValue()) |default_value| {
if (field_attrs.defaultValue(field_type)) |default_value| {
try out.appendSlice(gpa, " = ");
switch (@typeInfo(@TypeOf(default_value))) {
switch (@typeInfo(field_type)) {
.@"enum" => try out.print(gpa, ".{s},\n", .{@tagName(default_value)}),
.@"struct" => |info| {
try printStructValue(options, out, info, default_value, indent + 4);
},
else => try printType(options, out, @TypeOf(default_value), default_value, indent, null),
else => try printType(options, out, field_type, default_value, indent, null),
}
} else {
try out.appendSlice(gpa, ",\n");
@@ -368,8 +374,8 @@ fn printStruct(options: *Options, out: *std.ArrayList(u8), comptime T: type, com
try out.appendNTimes(gpa, ' ', indent);
try out.appendSlice(gpa, "};\n");
inline for (val.fields) |field| {
try printUserDefinedType(options, out, field.type, 0);
inline for (val.field_types) |field_type| {
try printUserDefinedType(options, out, field_type, 0);
}
}
@@ -384,24 +390,24 @@ fn printStructValue(
try out.appendSlice(gpa, ".{\n");
if (struct_val.is_tuple) {
inline for (struct_val.fields) |field| {
inline for (struct_val.field_names) |field_name| {
try out.appendNTimes(gpa, ' ', indent);
try printType(options, out, @TypeOf(@field(val, field.name)), @field(val, field.name), indent, null);
try printType(options, out, @TypeOf(@field(val, field_name)), @field(val, field_name), indent, null);
}
} else {
inline for (struct_val.fields) |field| {
inline for (struct_val.field_names) |field_name| {
try out.appendNTimes(gpa, ' ', indent);
try out.print(gpa, " .{f} = ", .{
std.zig.fmtIdFlags(field.name, .{ .allow_primitive = true, .allow_underscore = true }),
std.zig.fmtIdFlags(field_name, .{ .allow_primitive = true, .allow_underscore = true }),
});
const field_name = @field(val, field.name);
switch (@typeInfo(@TypeOf(field_name))) {
.@"enum" => try out.print(gpa, ".{s},\n", .{@tagName(field_name)}),
const field_val = @field(val, field_name);
switch (@typeInfo(@TypeOf(field_val))) {
.@"enum" => try out.print(gpa, ".{s},\n", .{@tagName(field_val)}),
.@"struct" => |struct_info| {
try printStructValue(options, out, struct_info, field_name, indent + 4);
try printStructValue(options, out, struct_info, field_val, indent + 4);
},
else => try printType(options, out, @TypeOf(field_name), field_name, indent, null),
else => try printType(options, out, @TypeOf(field_val), field_val, indent, null),
}
}
}
+7 -6
View File
@@ -396,12 +396,13 @@ pub const Operation = union(enum) {
};
pub const Result = Result: {
const operation_fields = @typeInfo(Operation).@"union".fields;
var field_names: [operation_fields.len][]const u8 = undefined;
var field_types: [operation_fields.len]type = undefined;
for (operation_fields, &field_names, &field_types) |field, *field_name, *field_type| {
field_name.* = field.name;
field_type.* = if (field.type == noreturn) noreturn else field.type.Result;
const operation_info = @typeInfo(Operation).@"union";
const operation_count = operation_info.field_names.len;
var field_names: [operation_count][]const u8 = undefined;
var field_types: [operation_count]type = undefined;
for (operation_info.field_names, operation_info.field_types, &field_names, &field_types) |f_name, f_type, *field_name, *field_type| {
field_name.* = f_name;
field_type.* = if (f_type == noreturn) noreturn else f_type.Result;
}
break :Result @Union(.auto, Tag, &field_names, &field_types, &@splat(.{}));
};
+1 -1
View File
@@ -1277,7 +1277,7 @@ pub fn takeEnum(r: *Reader, comptime Enum: type, endian: std.builtin.Endian) Tak
/// Asserts the buffer was initialized with a capacity at least `@sizeOf(Enum)`.
pub fn takeEnumNonexhaustive(r: *Reader, comptime Enum: type, endian: std.builtin.Endian) Error!Enum {
const info = @typeInfo(Enum).@"enum";
comptime assert(!info.is_exhaustive);
comptime assert(info.mode != .exhaustive);
comptime assert(@bitSizeOf(info.tag_type) == @sizeOf(info.tag_type) * 8);
return takeEnum(r, Enum, endian) catch |err| switch (err) {
error.InvalidEnumTag => unreachable,
+10 -10
View File
@@ -332,8 +332,8 @@ pub const Environ = struct {
.flags = .{ .nonblocking = true },
};
};
} else inline for (@typeInfo(String).@"struct".fields) |field| {
if (std.mem.eql(u8, key, field.name)) @field(environ.string, field.name) = value;
} else inline for (@typeInfo(String).@"struct".field_names) |field_name| {
if (std.mem.eql(u8, key, field_name)) @field(environ.string, field_name) = value;
}
}
}
@@ -11785,8 +11785,8 @@ fn sleepWasi(t: *Threaded, timeout: Io.Timeout) Io.Cancelable!void {
fn sleepNanosleep(t: *Threaded, timeout: Io.Timeout) Io.Cancelable!void {
const t_io = io(t);
const sec_type = @typeInfo(posix.timespec).@"struct".fields[0].type;
const nsec_type = @typeInfo(posix.timespec).@"struct".fields[1].type;
const sec_type = @typeInfo(posix.timespec).@"struct".field_types[0];
const nsec_type = @typeInfo(posix.timespec).@"struct".field_types[1];
var timespec: posix.timespec = t: {
const d = timeout.toDurationFromNow(t_io) orelse break :t .{
@@ -14923,9 +14923,9 @@ const WindowsEnvironStrings = struct {
i += 1; // skip over null byte
inline for (@typeInfo(WindowsEnvironStrings).@"struct".fields) |field| {
const field_name_w = comptime std.unicode.wtf8ToWtf16LeStringLiteral(field.name);
if (windows.eqlIgnoreCaseWtf16(key_w, field_name_w)) @field(result, field.name) = value_w;
inline for (@typeInfo(WindowsEnvironStrings).@"struct".field_names) |field_name| {
const field_name_w = comptime std.unicode.wtf8ToWtf16LeStringLiteral(field_name);
if (windows.eqlIgnoreCaseWtf16(key_w, field_name_w)) @field(result, field_name) = value_w;
}
}
@@ -16190,7 +16190,7 @@ fn windowsCreateProcessPathExt(
}
var io_status: windows.IO_STATUS_BLOCK = undefined;
const num_supported_pathext = @typeInfo(process.WindowsExtension).@"enum".fields.len;
const num_supported_pathext = @typeInfo(process.WindowsExtension).@"enum".field_names.len;
var pathext_seen: [num_supported_pathext]bool = @splat(false);
var any_pathext_seen = false;
var unappended_exists = false;
@@ -16435,8 +16435,8 @@ fn windowsCreateProcess(
fn windowsCreateProcessSupportsExtension(ext: []const u16) ?process.WindowsExtension {
comptime {
// Ensures keeping this function in sync with the enum.
const fields = @typeInfo(process.WindowsExtension).@"enum".fields;
assert(fields.len == 4);
const field_names = @typeInfo(process.WindowsExtension).@"enum".field_names;
assert(field_names.len == 4);
assert(@intFromEnum(process.WindowsExtension.bat) == 0);
assert(@intFromEnum(process.WindowsExtension.cmd) == 1);
assert(@intFromEnum(process.WindowsExtension.com) == 2);
+18 -18
View File
@@ -620,14 +620,14 @@ pub fn print(w: *Writer, comptime fmt: []const u8, args: anytype) Error!void {
@compileError("expected tuple or struct argument, found " ++ @typeName(ArgsType));
}
const fields_info = args_type_info.@"struct".fields;
const field_names = args_type_info.@"struct".field_names;
const max_format_args = @typeInfo(std.fmt.ArgSetType).int.bits;
if (fields_info.len > max_format_args) {
if (field_names.len > max_format_args) {
@compileError("32 arguments max are supported per format call");
}
@setEvalBranchQuota(@as(comptime_int, fmt.len) * 1000); // NOTE: We're upcasting as 16-bit usize overflows.
comptime var arg_state: std.fmt.ArgState = .{ .args_len = fields_info.len };
comptime var arg_state: std.fmt.ArgState = .{ .args_len = field_names.len };
comptime var i = 0;
comptime var literal: []const u8 = "";
inline while (true) {
@@ -728,7 +728,7 @@ pub fn print(w: *Writer, comptime fmt: []const u8, args: anytype) Error!void {
.width = width,
.precision = precision,
},
@field(args, fields_info[arg_to_print].name),
@field(args, field_names[arg_to_print]),
std.options.fmt_max_depth,
);
}
@@ -1290,7 +1290,7 @@ pub fn printValue(
.@"enum" => |info| {
if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
optionsForbidden(options);
if (info.is_exhaustive) {
if (info.mode == .exhaustive) {
return printEnumExhaustive(w, value);
} else {
return printEnumNonexhaustive(w, value);
@@ -1309,9 +1309,9 @@ pub fn printValue(
try w.writeAll(".{ .");
try w.writeAll(@tagName(@as(UnionTagType, value)));
try w.writeAll(" = ");
inline for (info.fields) |u_field| {
if (value == @field(UnionTagType, u_field.name)) {
try w.printValue(ANY, options, @field(value, u_field.name), max_depth - 1);
inline for (info.field_names) |u_field_name| {
if (value == @field(UnionTagType, u_field_name)) {
try w.printValue(ANY, options, @field(value, u_field_name), max_depth - 1);
}
}
try w.writeAll(" }");
@@ -1320,14 +1320,14 @@ pub fn printValue(
return w.writeAll(".{ ... }");
},
.@"extern", .@"packed" => {
if (info.fields.len == 0) return w.writeAll(".{}");
if (info.field_names.len == 0) return w.writeAll(".{}");
try w.writeAll(".{ ");
inline for (info.fields, 1..) |field, i| {
inline for (info.field_names, 1..) |field_name, i| {
try w.writeByte('.');
try w.writeAll(field.name);
try w.writeAll(field_name);
try w.writeAll(" = ");
try w.printValue(ANY, options, @field(value, field.name), max_depth - 1);
try w.writeAll(if (i < info.fields.len) ", " else " }");
try w.printValue(ANY, options, @field(value, field_name), max_depth - 1);
try w.writeAll(if (i < info.field_names.len) ", " else " }");
}
},
}
@@ -1344,13 +1344,13 @@ pub fn printValue(
return;
}
try w.writeAll(".{");
inline for (info.fields, 0..) |f, i| {
inline for (info.field_names, 0..) |f_name, i| {
if (i == 0) {
try w.writeAll(" ");
} else {
try w.writeAll(", ");
}
try w.printValue(ANY, options, @field(value, f.name), max_depth - 1);
try w.printValue(ANY, options, @field(value, f_name), max_depth - 1);
}
try w.writeAll(" }");
return;
@@ -1360,15 +1360,15 @@ pub fn printValue(
return;
}
try w.writeAll(".{");
inline for (info.fields, 0..) |f, i| {
inline for (info.field_names, 0..) |f_name, i| {
if (i == 0) {
try w.writeAll(" .");
} else {
try w.writeAll(", .");
}
try w.writeAll(f.name);
try w.writeAll(f_name);
try w.writeAll(" = ");
try w.printValue(ANY, options, @field(value, f.name), max_depth - 1);
try w.printValue(ANY, options, @field(value, f_name), max_depth - 1);
}
try w.writeAll(" }");
},
+2 -2
View File
@@ -867,8 +867,8 @@ const TreeSymbol = enum {
fn maxByteLen(symbol: TreeSymbol) usize {
var max: usize = 0;
inline for (@typeInfo(Encoding).@"enum".fields) |field| {
const len = symbol.bytes(@field(Encoding, field.name)).len;
inline for (@typeInfo(Encoding).@"enum".field_names) |field_name| {
const len = symbol.bytes(@field(Encoding, field_name)).len;
max = @max(max, len);
}
return max;
+4 -4
View File
@@ -1764,10 +1764,10 @@ pub const Cpu = struct {
fn allCpusFromDecls(comptime cpus: type) []const *const Cpu.Model {
@setEvalBranchQuota(2000);
const decls = @typeInfo(cpus).@"struct".decls;
var array: [decls.len]*const Cpu.Model = undefined;
for (decls, 0..) |decl, i| {
array[i] = &@field(cpus, decl.name);
const decl_names = @typeInfo(cpus).@"struct".decl_names;
var array: [decl_names.len]*const Cpu.Model = undefined;
for (decl_names, 0..) |decl_name, i| {
array[i] = &@field(cpus, decl_name);
}
const finalized = array;
return &finalized;
+2 -2
View File
@@ -291,7 +291,7 @@ pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
@setEvalBranchQuota(2000);
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.a320)] = .{
@@ -2019,7 +2019,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -17,7 +17,7 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.bwx)] = .{
@@ -43,7 +43,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -268,7 +268,7 @@ pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
@setEvalBranchQuota(2000);
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.@"1024_addressable_vgprs")] = .{
@@ -1877,7 +1877,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -14,7 +14,7 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.norm)] = .{
@@ -25,7 +25,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -215,7 +215,7 @@ pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
@setEvalBranchQuota(10000);
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.@"32bit")] = .{
@@ -1736,7 +1736,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -52,7 +52,7 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.addsubiw)] = .{
@@ -388,7 +388,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -17,7 +17,7 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.allows_misaligned_mem_access)] = .{
@@ -43,7 +43,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -76,7 +76,7 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.@"10e60")] = .{
@@ -418,7 +418,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -60,7 +60,7 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.audio)] = .{
@@ -334,7 +334,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -18,7 +18,7 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.@"64bit")] = .{
@@ -56,7 +56,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -16,7 +16,7 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.v3_1)] = .{
@@ -41,7 +41,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -12,13 +12,13 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -34,7 +34,7 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.@"32bit")] = .{
@@ -153,7 +153,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -36,7 +36,7 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.isa_68000)] = .{
@@ -170,7 +170,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -70,7 +70,7 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.abs2008)] = .{
@@ -425,7 +425,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -17,7 +17,7 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.ext)] = .{
@@ -43,7 +43,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -84,7 +84,7 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.ptx32)] = .{
@@ -445,7 +445,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -93,7 +93,7 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.@"64bit")] = .{
@@ -595,7 +595,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -14,7 +14,7 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.p2)] = .{
@@ -25,7 +25,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -361,7 +361,7 @@ pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
@setEvalBranchQuota(2000);
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.@"32bit")] = .{
@@ -2675,7 +2675,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -62,7 +62,7 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.backchain)] = .{
@@ -313,7 +313,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -72,7 +72,7 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.@"64bit")] = .{
@@ -395,7 +395,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -29,7 +29,7 @@ pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
@setEvalBranchQuota(2000);
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.arbitrary_precision_integers)] = .{
@@ -138,7 +138,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -14,7 +14,7 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.vpu)] = .{
@@ -25,7 +25,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -32,7 +32,7 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.atomics)] = .{
@@ -139,7 +139,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -215,7 +215,7 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.@"16bit_mode")] = .{
@@ -1374,7 +1374,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -12,13 +12,13 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+2 -2
View File
@@ -50,7 +50,7 @@ pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
pub const all_features = blk: {
const len = @typeInfo(Feature).@"enum".fields.len;
const len = @typeInfo(Feature).@"enum".field_names.len;
std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
var result: [len]CpuFeature = undefined;
result[@intFromEnum(Feature.bool)] = .{
@@ -251,7 +251,7 @@ pub const all_features = blk: {
const ti = @typeInfo(Feature);
for (&result, 0..) |*elem, i| {
elem.index = i;
elem.name = ti.@"enum".fields[i].name;
elem.name = ti.@"enum".field_names[i];
}
break :blk result;
};
+1 -1
View File
@@ -54,7 +54,7 @@ pub const EXC = enum(exception_type_t) {
_,
pub const TYPES_COUNT = @typeInfo(EXC).@"enum".fields.len;
pub const TYPES_COUNT = @typeInfo(EXC).@"enum".field_names.len;
pub const SOFT_SIGNAL = 0x10003;
pub const MASK = packed struct(u32) {
+1 -1
View File
@@ -1386,7 +1386,7 @@ pub const IMAGE = struct {
RESERVED = 15,
_,
pub const len = @typeInfo(IMAGE.DIRECTORY_ENTRY).@"enum".fields.len;
pub const len = @typeInfo(IMAGE.DIRECTORY_ENTRY).@"enum".field_names.len;
};
pub const FILE = struct {
+8 -8
View File
@@ -177,27 +177,27 @@ pub fn StaticMap(comptime Enum: type) type {
pub fn initComptime(comptime key_pairs: anytype) ReturnType {
const struct_info = @typeInfo(@TypeOf(key_pairs)).@"struct";
const error_msg = "Each field of '" ++ @typeName(Enum) ++ "' must map to exactly one OID";
if (!enum_info.is_exhaustive or enum_info.fields.len != struct_info.fields.len) {
if (enum_info.mode == .nonexhaustive or enum_info.field_names.len != struct_info.field_names.len) {
@compileError(error_msg);
}
comptime var enum_to_oid = EnumToOid.initUndefined();
const KeyPair = struct { []const u8, Enum };
comptime var static_key_pairs: [enum_info.fields.len]KeyPair = undefined;
comptime var static_key_pairs: [enum_info.field_names.len]KeyPair = undefined;
comptime for (enum_info.fields, 0..) |f, i| {
if (!@hasField(@TypeOf(key_pairs), f.name)) {
@compileError("Field '" ++ f.name ++ "' missing Oid.StaticMap entry");
comptime for (enum_info.field_names, enum_info.field_values, 0..) |f_name, f_value, i| {
if (!@hasField(@TypeOf(key_pairs), f_name)) {
@compileError("Field '" ++ f_name ++ "' missing Oid.StaticMap entry");
}
const encoded = &encodeComptime(@field(key_pairs, f.name));
const tag: Enum = @enumFromInt(f.value);
const encoded = &encodeComptime(@field(key_pairs, f_name));
const tag: Enum = @enumFromInt(f_value);
static_key_pairs[i] = .{ encoded, tag };
enum_to_oid.set(tag, encoded);
};
const oid_to_enum = std.StaticStringMap(Enum).initComptime(static_key_pairs);
if (oid_to_enum.values().len != enum_info.fields.len) @compileError(error_msg);
if (oid_to_enum.values().len != enum_info.field_names.len) @compileError(error_msg);
return ReturnType{ .oid_to_enum = oid_to_enum, .enum_to_oid = enum_to_oid };
}
+7 -7
View File
@@ -19,14 +19,14 @@ pub fn any(self: *Decoder, comptime T: type) !T {
const tag = Tag.fromZig(T).toExpected();
switch (@typeInfo(T)) {
.@"struct" => {
.@"struct" => |info| {
const ele = try self.element(tag);
defer self.index = ele.slice.end; // don't force parsing all fields
var res: T = undefined;
inline for (std.meta.fields(T)) |f| {
self.field_tag = FieldTag.fromContainer(T, f.name);
inline for (info.field_names, info.field_types, info.field_attrs) |f_name, f_type, f_attrs| {
self.field_tag = FieldTag.fromContainer(T, f_name);
if (self.field_tag) |ft| {
if (ft.explicit) {
@@ -36,15 +36,15 @@ pub fn any(self: *Decoder, comptime T: type) !T {
}
}
@field(res, f.name) = self.any(f.type) catch |err| brk: {
if (f.defaultValue()) |d| {
@field(res, f_name) = self.any(f_type) catch |err| brk: {
if (f_attrs.defaultValue(f_type)) |d| {
break :brk d;
}
return err;
};
// DER encodes null values by skipping them.
if (@typeInfo(f.type) == .optional and @field(res, f.name) == null) {
if (f.defaultValue()) |d| @field(res, f.name) = d;
if (@typeInfo(f_type) == .optional and @field(res, f_name) == null) {
if (f_attrs.defaultValue(f_type)) |d| @field(res, f_name) = d;
}
}
+10 -8
View File
@@ -29,16 +29,18 @@ fn anyTag(self: *Encoder, tag_: Tag, val: anytype) !void {
switch (@typeInfo(T)) {
.@"struct" => |info| {
inline for (0..info.fields.len) |i| {
const f = info.fields[info.fields.len - i - 1];
const field_val = @field(val, f.name);
const field_tag = FieldTag.fromContainer(T, f.name);
inline for (0..info.field_names.len) |i| {
const f_idx = info.field_names.len - i - 1;
const f_name = info.field_names[f_idx];
const f_type = info.field_types[f_idx];
const f_attrs = info.field_attrs[f_idx];
const field_val = @field(val, f_name);
const field_tag = FieldTag.fromContainer(T, f_name);
// > The encoding of a set value or sequence value shall not include an encoding for any
// > component value which is equal to its default value.
const is_default = if (f.is_comptime) false else if (f.default_value_ptr) |v| brk: {
const default_val: *const f.type = @ptrCast(@alignCast(v));
break :brk std.mem.eql(u8, std.mem.asBytes(default_val), std.mem.asBytes(&field_val));
const is_default = if (f_attrs.@"comptime") false else if (f_attrs.defaultValue(f_type)) |default_val| brk: {
break :brk std.mem.eql(u8, std.mem.asBytes(&default_val), std.mem.asBytes(&field_val));
} else false;
if (!is_default) {
@@ -46,7 +48,7 @@ fn anyTag(self: *Encoder, tag_: Tag, val: anytype) !void {
self.field_tag = field_tag;
// will merge with self.field_tag.
// may mutate self.field_tag.
try self.anyTag(Tag.fromZig(f.type), field_val);
try self.anyTag(Tag.fromZig(f_type), field_val);
if (field_tag) |ft| {
if (ft.explicit) {
try self.length(self.buffer.data.len - start2);
+23 -20
View File
@@ -115,22 +115,23 @@ pub fn deserialize(comptime HashResult: type, str: []const u8) Error!HashResult
while (it_params.next()) |params| {
const param = kvSplit(params) catch break;
var found = false;
inline for (comptime meta.fields(HashResult)) |p| {
if (mem.eql(u8, p.name, param.key)) {
switch (@typeInfo(p.type)) {
.int => @field(out, p.name) = fmt.parseUnsigned(
p.type,
const info = @typeInfo(HashResult).@"struct";
inline for (info.field_names, info.field_types) |p_name, p_type| {
if (mem.eql(u8, p_name, param.key)) {
switch (@typeInfo(p_type)) {
.int => @field(out, p_name) = fmt.parseUnsigned(
p_type,
param.value,
10,
) catch return Error.InvalidEncoding,
.pointer => |ptr| {
if (!ptr.is_const) @compileError("Value slice must be constant");
@field(out, p.name) = param.value;
if (!ptr.attrs.@"const") @compileError("Value slice must be constant");
@field(out, p_name) = param.value;
},
.@"struct" => try @field(out, p.name).fromB64(param.value),
.@"struct" => try @field(out, p_name).fromB64(param.value),
else => std.debug.panic(
"Value for [{s}] must be an integer, a constant slice or a BinValue",
.{p.name},
.{p_name},
),
}
set_fields += 1;
@@ -167,8 +168,9 @@ pub fn deserialize(comptime HashResult: type, str: []const u8) Error!HashResult
// Check that all the required fields have been set, excluding optional values and parameters
// with default values
var expected_fields: usize = 0;
inline for (comptime meta.fields(HashResult)) |p| {
if (@typeInfo(p.type) != .optional and p.default_value_ptr == null) {
const info = @typeInfo(HashResult).@"struct";
inline for (info.field_types, info.field_attrs) |p_type, p_attrs| {
if (@typeInfo(p_type) != .optional and p_attrs.default_value_ptr == null) {
expected_fields += 1;
}
}
@@ -228,21 +230,22 @@ fn serializeTo(params: anytype, out: *std.Io.Writer) !void {
}
var has_params = false;
inline for (comptime meta.fields(HashResult)) |p| {
if (comptime !(mem.eql(u8, p.name, "alg_id") or
mem.eql(u8, p.name, "alg_version") or
mem.eql(u8, p.name, "hash") or
mem.eql(u8, p.name, "salt")))
const info = @typeInfo(HashResult).@"struct";
inline for (info.field_names, info.field_types) |p_name, p_type| {
if (comptime !(mem.eql(u8, p_name, "alg_id") or
mem.eql(u8, p_name, "alg_version") or
mem.eql(u8, p_name, "hash") or
mem.eql(u8, p_name, "salt")))
{
const value = @field(params, p.name);
const value = @field(params, p_name);
try out.writeAll(if (has_params) params_delimiter else fields_delimiter);
if (@typeInfo(p.type) == .@"struct") {
if (@typeInfo(p_type) == .@"struct") {
var buf: [@TypeOf(value).max_encoded_length]u8 = undefined;
try out.print("{s}{s}{s}", .{ p.name, kv_delimiter, try value.toB64(&buf) });
try out.print("{s}{s}{s}", .{ p_name, kv_delimiter, try value.toB64(&buf) });
} else {
try out.print(
if (@typeInfo(@TypeOf(value)) == .pointer) "{s}{s}{s}" else "{s}{s}{}",
.{ p.name, kv_delimiter, value },
.{ p_name, kv_delimiter, value },
);
}
has_params = true;
+1 -1
View File
@@ -135,7 +135,7 @@ fn markSecret(ptr: anytype, comptime action: enum { classify, declassify }) void
const t = @typeInfo(@TypeOf(ptr));
if (t != .pointer) @compileError("Pointer expected - Found: " ++ @typeName(@TypeOf(ptr)));
const p = t.pointer;
if (p.is_allowzero) @compileError("A nullable pointer is always assumed to leak information via side channels");
if (p.attrs.@"allowzero") @compileError("A nullable pointer is always assumed to leak information via side channels");
const child = @typeInfo(p.child);
switch (child) {
+1 -1
View File
@@ -710,7 +710,7 @@ pub const Decoder = struct {
else => @compileError("unsupported int type: " ++ @typeName(T)),
},
.@"enum" => |info| {
if (info.is_exhaustive) @compileError("exhaustive enum cannot be used");
if (info.mode == .exhaustive) @compileError("exhaustive enum cannot be used");
return @enumFromInt(d.decode(info.tag_type));
},
else => @compileError("unsupported type: " ++ @typeName(T)),
+3 -3
View File
@@ -1338,11 +1338,11 @@ fn failRead(c: *Client, err: ReadError) error{ReadFailed} {
}
fn logSecrets(w: *Writer, context: anytype, secrets: anytype) void {
inline for (@typeInfo(@TypeOf(secrets)).@"struct".fields) |field| w.print("{s}" ++
(if (@hasField(@TypeOf(context), "counter")) "_{d}" else "") ++ " {x} {x}\n", .{field.name} ++
inline for (@typeInfo(@TypeOf(secrets)).@"struct".field_names) |field_name| w.print("{s}" ++
(if (@hasField(@TypeOf(context), "counter")) "_{d}" else "") ++ " {x} {x}\n", .{field_name} ++
(if (@hasField(@TypeOf(context), "counter")) .{context.counter} else .{}) ++ .{
context.client_random,
@field(secrets, field.name),
@field(secrets, field_name),
}) catch {};
}
+12 -8
View File
@@ -219,9 +219,10 @@ pub fn load(
break :dwarf null; // debug info not present
}
var sections: Dwarf.SectionArray = @splat(null);
inline for (@typeInfo(Dwarf.Section.Id).@"enum".fields) |f| {
if (result.sections.get(@field(Section.Id, f.name))) |s| {
sections[f.value] = .{ .data = s.bytes, .owned = false };
const info = @typeInfo(Dwarf.Section.Id).@"enum";
inline for (info.field_names, info.field_values) |f_name, f_value| {
if (result.sections.get(@field(Section.Id, f_name))) |s| {
sections[f_value] = .{ .data = s.bytes, .owned = false };
}
}
break :dwarf .{ .sections = sections };
@@ -408,8 +409,8 @@ fn loadSeparateDebugFile(
return null;
}
inline for (@typeInfo(Dwarf.Section.Id).@"enum".fields) |f| {
const id = @field(Section.Id, f.name);
inline for (@typeInfo(Dwarf.Section.Id).@"enum".field_names) |f_name| {
const id = @field(Section.Id, f_name);
if (main_loaded.sections.get(id) == null) {
main_loaded.sections.set(id, result.sections.get(id));
}
@@ -498,9 +499,12 @@ fn loadInner(
if (shdr.sh_name > shstrtab.len) return error.TruncatedElfFile;
const name = std.mem.sliceTo(shstrtab[@intCast(shdr.sh_name)..], 0);
const section_id: Section.Id = inline for (@typeInfo(Section.Id).@"enum".fields) |s| {
if (std.mem.eql(u8, "." ++ s.name, name)) {
break @enumFromInt(s.value);
const section_id: Section.Id = inline for (
@typeInfo(Section.Id).@"enum".field_names,
@typeInfo(Section.Id).@"enum".field_values,
) |s_name, s_value| {
if (std.mem.eql(u8, "." ++ s_name, name)) {
break @enumFromInt(s_value);
}
} else continue;
+2 -2
View File
@@ -504,8 +504,8 @@ fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile {
if (!std.mem.eql(u8, "__DWARF", sect.segName())) continue;
const section_index: usize = inline for (@typeInfo(Dwarf.Section.Id).@"enum".fields, 0..) |section, i| {
if (mem.eql(u8, "__" ++ section.name, sect.sectName())) break i;
const section_index: usize = inline for (@typeInfo(Dwarf.Section.Id).@"enum".field_names, 0..) |section_name, i| {
if (mem.eql(u8, "__" ++ section_name, sect.sectName())) break i;
} else continue;
if (mapped_ofile.len < sect.offset + sect.size) return error.InvalidMachO;
+2 -2
View File
@@ -408,8 +408,8 @@ fn unwindFrameInner(si: *SelfInfo, io: Io, context: *UnwindContext) !usize {
const ip_ptr = fp + @sizeOf(usize);
var reg_addr = fp - @sizeOf(usize);
inline for (@typeInfo(@TypeOf(frame.x_reg_pairs)).@"struct".fields, 0..) |field, i| {
if (@field(frame.x_reg_pairs, field.name) != 0) {
inline for (@typeInfo(@TypeOf(frame.x_reg_pairs)).@"struct".field_names, 0..) |field_name, i| {
if (@field(frame.x_reg_pairs, field_name) != 0) {
(try dwarfRegNative(&context.cpu_state, 19 + i)).* = @as(*const usize, @ptrFromInt(reg_addr)).*;
reg_addr += @sizeOf(usize);
(try dwarfRegNative(&context.cpu_state, 20 + i)).* = @as(*const usize, @ptrFromInt(reg_addr)).*;
+2 -2
View File
@@ -513,8 +513,8 @@ const Module = struct {
if (coff_obj.getSectionByName(".debug_info") == null) break :dwarf null;
var sections: Dwarf.SectionArray = undefined;
inline for (@typeInfo(Dwarf.Section.Id).@"enum".fields, 0..) |section, i| {
sections[i] = if (coff_obj.getSectionByName("." ++ section.name)) |section_header| .{
inline for (@typeInfo(Dwarf.Section.Id).@"enum".field_names, 0..) |section_name, i| {
sections[i] = if (coff_obj.getSectionByName("." ++ section_name)) |section_header| .{
.data = try coff_obj.getSectionDataAlloc(section_header, arena),
.owned = false,
} else null;
+7 -7
View File
@@ -484,7 +484,7 @@ pub const PT = enum(Word) {
_,
/// Number of defined types
pub const NUM = @typeInfo(PT).@"enum".fields.len;
pub const NUM = @typeInfo(PT).@"enum".field_names.len;
/// Start of OS-specific
pub const LOOS: PT = @enumFromInt(0x60000000);
@@ -552,7 +552,7 @@ pub const SHT = enum(Word) {
_,
/// Number of defined types
pub const NUM = @typeInfo(SHT).@"enum".fields.len;
pub const NUM = @typeInfo(SHT).@"enum".field_names.len;
/// Start of OS-specific
pub const LOOS: SHT = @enumFromInt(0x60000000);
@@ -595,7 +595,7 @@ pub const STB = enum(u4) {
_,
/// Number of defined types
pub const NUM = @typeInfo(STB).@"enum".fields.len;
pub const NUM = @typeInfo(STB).@"enum".field_names.len;
/// Start of OS-specific
pub const LOOS: STB = @enumFromInt(10);
@@ -631,7 +631,7 @@ pub const STT = enum(u4) {
_,
/// Number of defined types
pub const NUM = @typeInfo(STT).@"enum".fields.len;
pub const NUM = @typeInfo(STT).@"enum".field_names.len;
/// Start of OS-specific
pub const LOOS: STT = @enumFromInt(10);
@@ -815,7 +815,7 @@ pub const Header = struct {
pub fn init(hdr: anytype, endian: Endian) Header {
// Converting integers to exhaustive enums using `@enumFromInt` could cause a panic.
comptime assert(!@typeInfo(OSABI).@"enum".is_exhaustive);
comptime assert(@typeInfo(OSABI).@"enum".mode == .nonexhaustive);
return .{
.is_64 = switch (@TypeOf(hdr)) {
Elf32_Ehdr => false,
@@ -1642,7 +1642,7 @@ pub const CLASS = enum(u8) {
@"64" = 2,
_,
pub const NUM = @typeInfo(CLASS).@"enum".fields.len;
pub const NUM = @typeInfo(CLASS).@"enum".field_names.len;
pub fn ElfN(comptime class: CLASS) type {
return switch (class) {
@@ -1667,7 +1667,7 @@ pub const DATA = enum(u8) {
@"2MSB" = 2,
_,
pub const NUM = @typeInfo(DATA).@"enum".fields.len;
pub const NUM = @typeInfo(DATA).@"enum".field_names.len;
};
pub const OSABI = enum(u8) {
+65 -66
View File
@@ -3,14 +3,13 @@
const std = @import("std");
const assert = std.debug.assert;
const testing = std.testing;
const EnumField = std.builtin.Type.EnumField;
/// Increment this value when adding APIs that add single backwards branches.
const eval_branch_quota_cushion = 10;
pub fn fromInt(comptime E: type, integer: anytype) ?E {
const enum_info = @typeInfo(E).@"enum";
if (!enum_info.is_exhaustive) {
if (enum_info.mode == .nonexhaustive) {
if (std.math.cast(enum_info.tag_type, integer)) |tag| {
return @enumFromInt(tag);
}
@@ -32,20 +31,19 @@ pub fn fromInt(comptime E: type, integer: anytype) ?E {
/// the first name is used. Each field is of type Data and has the provided
/// default, which may be undefined.
pub fn EnumFieldStruct(comptime E: type, comptime Data: type, comptime field_default: ?Data) type {
@setEvalBranchQuota(@typeInfo(E).@"enum".fields.len + eval_branch_quota_cushion);
@setEvalBranchQuota(@typeInfo(E).@"enum".field_names.len + eval_branch_quota_cushion);
const default_ptr: ?*const anyopaque = if (field_default) |d| @ptrCast(&d) else null;
return @Struct(.auto, null, std.meta.fieldNames(E), &@splat(Data), &@splat(.{ .default_value_ptr = default_ptr }));
}
/// Looks up the supplied fields in the given enum type.
/// Uses only the field names, field values are ignored.
/// Looks up the supplied field values in the given enum type.
/// The result array is in the same order as the input.
pub inline fn valuesFromFields(comptime E: type, comptime fields: []const EnumField) []const E {
pub inline fn valuesFromFields(comptime E: type, comptime field_values: []const comptime_int) []const E {
comptime {
@setEvalBranchQuota(@typeInfo(E).@"enum".fields.len + eval_branch_quota_cushion);
var result: [fields.len]E = undefined;
for (&result, fields) |*r, f| {
r.* = @enumFromInt(f.value);
@setEvalBranchQuota(@typeInfo(E).@"enum".field_names.len + eval_branch_quota_cushion);
var result: [field_values.len]E = undefined;
for (&result, field_values) |*r, f_value| {
r.* = @enumFromInt(f_value);
}
const final = result;
return &final;
@@ -55,17 +53,18 @@ pub inline fn valuesFromFields(comptime E: type, comptime fields: []const EnumFi
/// Returns the set of all named values in the given enum, in
/// declaration order.
pub inline fn values(comptime E: type) []const E {
return comptime valuesFromFields(E, @typeInfo(E).@"enum".fields);
return comptime valuesFromFields(E, @typeInfo(E).@"enum".field_values);
}
/// A safe alternative to @tagName() for non-exhaustive enums that doesn't
/// panic when `e` has no tagged value.
/// Returns the tag name for `e` or null if no tag exists.
pub fn tagName(comptime E: type, e: E) ?[:0]const u8 {
const fields = @typeInfo(E).@"enum".fields;
@setEvalBranchQuota(fields.len);
return inline for (fields) |f| {
if (@intFromEnum(e) == f.value) break f.name;
const field_names = @typeInfo(E).@"enum".field_names;
const field_values = @typeInfo(E).@"enum".field_values;
@setEvalBranchQuota(field_names.len);
return inline for (field_names, field_values) |f_name, f_value| {
if (@intFromEnum(e) == f_value) break f_name;
} else null;
}
@@ -88,20 +87,20 @@ test tagName {
pub fn directEnumArrayLen(comptime E: type, comptime max_unused_slots: comptime_int) comptime_int {
var max_value: comptime_int = -1;
const max_usize: comptime_int = ~@as(usize, 0);
const fields = @typeInfo(E).@"enum".fields;
for (fields) |f| {
if (f.value < 0) {
@compileError("Cannot create a direct enum array for " ++ @typeName(E) ++ ", field ." ++ f.name ++ " has a negative value.");
const info = @typeInfo(E).@"enum";
for (info.field_names, info.field_values) |f_name, f_value| {
if (f_value < 0) {
@compileError("Cannot create a direct enum array for " ++ @typeName(E) ++ ", field ." ++ f_name ++ " has a negative value.");
}
if (f.value > max_value) {
if (f.value > max_usize) {
@compileError("Cannot create a direct enum array for " ++ @typeName(E) ++ ", field ." ++ f.name ++ " is larger than the max value of usize.");
if (f_value > max_value) {
if (f_value > max_usize) {
@compileError("Cannot create a direct enum array for " ++ @typeName(E) ++ ", field ." ++ f_name ++ " is larger than the max value of usize.");
}
max_value = f.value;
max_value = f_value;
}
}
const unused_slots = max_value + 1 - fields.len;
const unused_slots = max_value + 1 - info.field_names.len;
if (unused_slots > max_unused_slots) {
const unused_str = std.fmt.comptimePrint("{d}", .{unused_slots});
const allowed_str = std.fmt.comptimePrint("{d}", .{max_unused_slots});
@@ -167,10 +166,10 @@ pub fn directEnumArrayDefault(
) [directEnumArrayLen(E, max_unused_slots)]Data {
const len = comptime directEnumArrayLen(E, max_unused_slots);
var result: [len]Data = @splat(default orelse undefined);
inline for (@typeInfo(@TypeOf(init_values)).@"struct".fields) |f| {
const enum_value = @field(E, f.name);
inline for (@typeInfo(@TypeOf(init_values)).@"struct".field_names) |f_name| {
const enum_value = @field(E, f_name);
const index = @as(usize, @intCast(@intFromEnum(enum_value)));
result[index] = @field(init_values, f.name);
result[index] = @field(init_values, f_name);
}
return result;
}
@@ -256,9 +255,9 @@ pub fn EnumSet(comptime E: type) type {
/// Initializes the set using a struct of bools
pub fn init(init_values: EnumFieldStruct(E, bool, false)) Self {
@setEvalBranchQuota(2 * @typeInfo(E).@"enum".fields.len);
@setEvalBranchQuota(2 * @typeInfo(E).@"enum".field_names.len);
var result: Self = .{};
if (@typeInfo(E).@"enum".is_exhaustive) {
if (@typeInfo(E).@"enum".mode == .exhaustive) {
inline for (0..Self.len) |i| {
const key = comptime Indexer.keyForIndex(i);
const tag = @tagName(key);
@@ -267,9 +266,9 @@ pub fn EnumSet(comptime E: type) type {
}
}
} else {
inline for (std.meta.fields(E)) |field| {
const key = @field(E, field.name);
if (@field(init_values, field.name)) {
inline for (@typeInfo(E).@"enum".field_names) |field_name| {
const key = @field(E, field_name);
if (@field(init_values, field_name)) {
const i = comptime Indexer.indexOf(key);
result.bits.set(i);
}
@@ -443,9 +442,9 @@ pub fn EnumMap(comptime E: type, comptime V: type) type {
/// Initializes the map using a sparse struct of optionals
pub fn init(init_values: EnumFieldStruct(E, ?Value, @as(?Value, null))) Self {
@setEvalBranchQuota(2 * @typeInfo(E).@"enum".fields.len);
@setEvalBranchQuota(2 * @typeInfo(E).@"enum".field_names.len);
var result: Self = .{};
if (@typeInfo(E).@"enum".is_exhaustive) {
if (@typeInfo(E).@"enum".mode == .exhaustive) {
inline for (0..Self.len) |i| {
const key = comptime Indexer.keyForIndex(i);
const tag = @tagName(key);
@@ -455,9 +454,9 @@ pub fn EnumMap(comptime E: type, comptime V: type) type {
}
}
} else {
inline for (std.meta.fields(E)) |field| {
const key = @field(E, field.name);
if (@field(init_values, field.name)) |*v| {
inline for (std.meta.fieldNames(E)) |field_name| {
const key = @field(E, field_name);
if (@field(init_values, field_name)) |*v| {
const i = comptime Indexer.indexOf(key);
result.bits.set(i);
result.values[i] = v.*;
@@ -487,7 +486,7 @@ pub fn EnumMap(comptime E: type, comptime V: type) type {
/// Initializes a full mapping with a provided default.
/// Consider using EnumArray instead if the map will remain full.
pub fn initFullWithDefault(comptime default: ?Value, init_values: EnumFieldStruct(E, Value, default)) Self {
@setEvalBranchQuota(2 * @typeInfo(E).@"enum".fields.len);
@setEvalBranchQuota(2 * @typeInfo(E).@"enum".field_names.len);
var result: Self = .{
.bits = .full,
.values = undefined,
@@ -673,11 +672,12 @@ pub fn BoundedEnumMultiset(comptime E: type, comptime CountSize: type) type {
/// Initializes the multiset using a struct of counts.
pub fn init(init_counts: EnumFieldStruct(E, CountSize, 0)) Self {
@setEvalBranchQuota(2 * @typeInfo(E).@"enum".fields.len);
@setEvalBranchQuota(2 * @typeInfo(E).@"enum".field_names.len);
var self = initWithCount(0);
inline for (@typeInfo(E).@"enum".fields) |field| {
const c = @field(init_counts, field.name);
const key = @as(E, @enumFromInt(field.value));
const info = @typeInfo(E).@"enum";
inline for (info.field_names, info.field_values) |field_name, field_value| {
const c = @field(init_counts, field_name);
const key: E = @enumFromInt(field_value);
self.counts.set(key, c);
}
return self;
@@ -745,16 +745,16 @@ pub fn BoundedEnumMultiset(comptime E: type, comptime CountSize: type) type {
/// Increases the all key counts by given multiset. Caller
/// asserts operation will not overflow any key.
pub fn addSetAssertSafe(self: *Self, other: Self) void {
inline for (@typeInfo(E).@"enum".fields) |field| {
const key = @as(E, @enumFromInt(field.value));
inline for (@typeInfo(E).@"enum".field_values) |field_value| {
const key = @as(E, @enumFromInt(field_value));
self.addAssertSafe(key, other.getCount(key));
}
}
/// Increases the all key counts by given multiset.
pub fn addSet(self: *Self, other: Self) error{Overflow}!void {
inline for (@typeInfo(E).@"enum".fields) |field| {
const key = @as(E, @enumFromInt(field.value));
inline for (@typeInfo(E).@"enum".field_values) |field_value| {
const key = @as(E, @enumFromInt(field_value));
try self.add(key, other.getCount(key));
}
}
@@ -763,8 +763,8 @@ pub fn BoundedEnumMultiset(comptime E: type, comptime CountSize: type) type {
/// the given multiset has more key counts than this,
/// then that key will have a key count of zero.
pub fn removeSet(self: *Self, other: Self) void {
inline for (@typeInfo(E).@"enum".fields) |field| {
const key = @as(E, @enumFromInt(field.value));
inline for (@typeInfo(E).@"enum".field_values) |field_value| {
const key = @as(E, @enumFromInt(field_value));
self.remove(key, other.getCount(key));
}
}
@@ -772,8 +772,8 @@ pub fn BoundedEnumMultiset(comptime E: type, comptime CountSize: type) type {
/// Returns true iff all key counts are the same as
/// given multiset.
pub fn eql(self: Self, other: Self) bool {
inline for (@typeInfo(E).@"enum".fields) |field| {
const key = @as(E, @enumFromInt(field.value));
inline for (@typeInfo(E).@"enum".field_values) |field_value| {
const key = @as(E, @enumFromInt(field_value));
if (self.getCount(key) != other.getCount(key)) {
return false;
}
@@ -784,8 +784,8 @@ pub fn BoundedEnumMultiset(comptime E: type, comptime CountSize: type) type {
/// Returns true iff all key counts less than or
/// equal to the given multiset.
pub fn subsetOf(self: Self, other: Self) bool {
inline for (@typeInfo(E).@"enum".fields) |field| {
const key = @as(E, @enumFromInt(field.value));
inline for (@typeInfo(E).@"enum".field_values) |field_value| {
const key = @as(E, @enumFromInt(field_value));
if (self.getCount(key) > other.getCount(key)) {
return false;
}
@@ -796,8 +796,8 @@ pub fn BoundedEnumMultiset(comptime E: type, comptime CountSize: type) type {
/// Returns true iff all key counts greater than or
/// equal to the given multiset.
pub fn supersetOf(self: Self, other: Self) bool {
inline for (@typeInfo(E).@"enum".fields) |field| {
const key = @as(E, @enumFromInt(field.value));
inline for (@typeInfo(E).@"enum".field_values) |field_value| {
const key = @as(E, @enumFromInt(field_value));
if (self.getCount(key) < other.getCount(key)) {
return false;
}
@@ -1075,7 +1075,7 @@ pub fn EnumArray(comptime E: type, comptime V: type) type {
/// Initializes values in the enum array, with the specified default.
pub fn initDefault(comptime default: ?Value, init_values: EnumFieldStruct(E, Value, default)) Self {
@setEvalBranchQuota(2 * @typeInfo(E).@"enum".fields.len);
@setEvalBranchQuota(2 * @typeInfo(E).@"enum".field_names.len);
var result: Self = .{ .values = undefined };
inline for (0..Self.len) |i| {
const key = comptime Indexer.keyForIndex(i);
@@ -1264,10 +1264,10 @@ test "EnumSet non-exhaustive" {
pub fn EnumIndexer(comptime E: type) type {
// n log n for `std.mem.sortUnstable` call below.
const fields_len = @typeInfo(E).@"enum".fields.len;
const fields_len = @typeInfo(E).@"enum".field_names.len;
@setEvalBranchQuota(3 * fields_len * std.math.log2(@max(fields_len, 1)) + eval_branch_quota_cushion);
if (!@typeInfo(E).@"enum".is_exhaustive) {
if (@typeInfo(E).@"enum".mode == .nonexhaustive) {
const BackingInt = @typeInfo(E).@"enum".tag_type;
if (@bitSizeOf(BackingInt) > @bitSizeOf(usize))
@compileError("Cannot create an enum indexer for a given non-exhaustive enum, tag_type is larger than usize.");
@@ -1315,18 +1315,17 @@ pub fn EnumIndexer(comptime E: type) type {
};
}
var fields: [fields_len]EnumField = @typeInfo(E).@"enum".fields[0..].*;
var field_values = @typeInfo(E).@"enum".field_values[0..fields_len].*;
std.mem.sortUnstable(EnumField, &fields, {}, struct {
fn lessThan(ctx: void, lhs: EnumField, rhs: EnumField) bool {
ctx;
return lhs.value < rhs.value;
std.mem.sortUnstable(comptime_int, &field_values, {}, struct {
fn lessThan(_: void, a: comptime_int, b: comptime_int) bool {
return a < b;
}
}.lessThan);
const min = fields[0].value;
const max = fields[fields_len - 1].value;
if (max - min == fields.len - 1) {
const min = field_values[0];
const max = field_values[fields_len - 1];
if (max - min == field_values.len - 1) {
return struct {
pub const Key = E;
pub const count: comptime_int = fields_len;
@@ -1343,7 +1342,7 @@ pub fn EnumIndexer(comptime E: type) type {
};
}
const keys = valuesFromFields(E, &fields);
const keys = valuesFromFields(E, &field_values);
return struct {
pub const Key = E;
+1 -1
View File
@@ -58,7 +58,7 @@ pub const ExecutionMode = union(Tag) {
/// Declare the mode entry point executes in.
pub fn executionMode(comptime entry_point: anytype, comptime mode: ExecutionMode) void {
const cc = @typeInfo(@TypeOf(entry_point)).@"fn".calling_convention;
const cc = @typeInfo(@TypeOf(entry_point)).@"fn".attrs.@"callconv";
switch (mode) {
.origin_upper_left,
.origin_lower_left,
+8 -8
View File
@@ -127,10 +127,10 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {
},
.@"struct" => |info| {
inline for (info.fields) |field| {
inline for (info.field_names) |field_name| {
// We reuse the hash of the previous field as the seed for the
// next one so that they're dependant.
hash(hasher, @field(key, field.name), strat);
hash(hasher, @field(key, field_name), strat);
}
},
@@ -138,10 +138,10 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {
if (info.tag_type) |tag_type| {
const tag = std.meta.activeTag(key);
hash(hasher, tag, strat);
inline for (info.fields) |field| {
if (@field(tag_type, field.name) == tag) {
if (field.type != void) {
hash(hasher, @field(key, field.name), strat);
inline for (info.field_names, info.field_types) |field_name, field_type| {
if (@field(tag_type, field_name) == tag) {
if (field_type != void) {
hash(hasher, @field(key, field_name), strat);
}
break :blk;
}
@@ -165,8 +165,8 @@ inline fn typeContainsSlice(comptime K: type) bool {
.pointer => |info| info.size == .slice,
inline .@"struct", .@"union" => |info| {
inline for (info.fields) |field| {
if (typeContainsSlice(field.type)) {
inline for (info.field_types) |field_type| {
if (typeContainsSlice(field_type)) {
return true;
}
}
+3 -3
View File
@@ -2,8 +2,8 @@ const std = @import("std");
fn hashMaybeSeed(comptime hash_fn: anytype, seed: anytype, buf: []const u8) @typeInfo(@TypeOf(hash_fn)).@"fn".return_type.? {
const HashFn = @typeInfo(@TypeOf(hash_fn)).@"fn";
if (HashFn.params.len > 1) {
if (@typeInfo(HashFn.params[0].type.?) == .int) {
if (HashFn.param_types.len > 1) {
if (@typeInfo(HashFn.param_types[0].?) == .int) {
return hash_fn(@intCast(seed), buf);
} else {
return hash_fn(buf, @intCast(seed));
@@ -15,7 +15,7 @@ fn hashMaybeSeed(comptime hash_fn: anytype, seed: anytype, buf: []const u8) @typ
fn initMaybeSeed(comptime Hash: anytype, seed: anytype) Hash {
const HashFn = @typeInfo(@TypeOf(Hash.init)).@"fn";
if (HashFn.params.len == 1) {
if (HashFn.param_types.len == 1) {
return Hash.init(@intCast(seed));
} else {
return Hash.init();
+2 -2
View File
@@ -823,8 +823,8 @@ pub const Request = struct {
/// Externally-owned; must outlive the Request.
privileged_headers: []const http.Header,
pub const default_accept_encoding: [@typeInfo(http.ContentEncoding).@"enum".fields.len]bool = b: {
var result: [@typeInfo(http.ContentEncoding).@"enum".fields.len]bool = @splat(false);
pub const default_accept_encoding: [@typeInfo(http.ContentEncoding).@"enum".field_names.len]bool = b: {
var result: [@typeInfo(http.ContentEncoding).@"enum".field_names.len]bool = @splat(false);
result[@intFromEnum(http.ContentEncoding.gzip)] = true;
result[@intFromEnum(http.ContentEncoding.deflate)] = true;
result[@intFromEnum(http.ContentEncoding.identity)] = true;
+14 -14
View File
@@ -401,9 +401,9 @@ pub fn write(self: *Stringify, v: anytype) Error!void {
return v.jsonStringify(self);
}
if (!enum_info.is_exhaustive) {
inline for (enum_info.fields) |field| {
if (v == @field(T, field.name)) {
if (enum_info.mode == .nonexhaustive) {
inline for (enum_info.field_names) |field_name| {
if (v == @field(T, field_name)) {
break;
}
} else {
@@ -424,15 +424,15 @@ pub fn write(self: *Stringify, v: anytype) Error!void {
const info = @typeInfo(T).@"union";
if (info.tag_type) |UnionTagType| {
try self.beginObject();
inline for (info.fields) |u_field| {
if (v == @field(UnionTagType, u_field.name)) {
try self.objectField(u_field.name);
if (u_field.type == void) {
inline for (info.field_names, info.field_types) |u_field_name, u_field_type| {
if (v == @field(UnionTagType, u_field_name)) {
try self.objectField(u_field_name);
if (u_field_type == void) {
// void v is {}
try self.beginObject();
try self.endObject();
} else {
try self.write(@field(v, u_field.name));
try self.write(@field(v, u_field_name));
}
break;
}
@@ -455,16 +455,16 @@ pub fn write(self: *Stringify, v: anytype) Error!void {
} else {
try self.beginObject();
}
inline for (S.fields) |Field| {
inline for (S.field_names, S.field_types) |field_name, field_type| {
// don't include void fields
if (Field.type == void) continue;
if (field_type == void) continue;
var emit_field = true;
// don't include optional fields that are null when emit_null_optional_fields is set to false
if (@typeInfo(Field.type) == .optional) {
if (@typeInfo(field_type) == .optional) {
if (self.options.emit_null_optional_fields == false) {
if (@field(v, Field.name) == null) {
if (@field(v, field_name) == null) {
emit_field = false;
}
}
@@ -472,9 +472,9 @@ pub fn write(self: *Stringify, v: anytype) Error!void {
if (emit_field) {
if (!S.is_tuple) {
try self.objectField(Field.name);
try self.objectField(field_name);
}
try self.write(@field(v, Field.name));
try self.write(@field(v, field_name));
}
}
if (S.is_tuple) {
+47 -31
View File
@@ -286,20 +286,20 @@ pub fn innerParse(
},
};
inline for (unionInfo.fields) |u_field| {
if (std.mem.eql(u8, u_field.name, field_name)) {
inline for (unionInfo.field_names, unionInfo.field_types) |u_field_name, u_field_type| {
if (std.mem.eql(u8, u_field_name, field_name)) {
// Free the name token now in case we're using an allocator that optimizes freeing the last allocated object.
// (Recursing into innerParse() might trigger more allocations.)
freeAllocated(allocator, name_token.?);
name_token = null;
if (u_field.type == void) {
if (u_field_type == void) {
// void isn't really a json type, but we can support void payload union tags with {} as a value.
if (.object_begin != try source.next()) return error.UnexpectedToken;
if (.object_end != try source.next()) return error.UnexpectedToken;
result = @unionInit(T, u_field.name, {});
result = @unionInit(T, u_field_name, {});
} else {
// Recurse.
result = @unionInit(T, u_field.name, try innerParse(u_field.type, allocator, source, options));
result = @unionInit(T, u_field_name, try innerParse(u_field_type, allocator, source, options));
}
break;
}
@@ -318,8 +318,8 @@ pub fn innerParse(
if (.array_begin != try source.next()) return error.UnexpectedToken;
var r: T = undefined;
inline for (0..structInfo.fields.len) |i| {
r[i] = try innerParse(structInfo.fields[i].type, allocator, source, options);
inline for (structInfo.field_types, 0..) |field_type, i| {
r[i] = try innerParse(field_type, allocator, source, options);
}
if (.array_end != try source.next()) return error.UnexpectedToken;
@@ -334,7 +334,7 @@ pub fn innerParse(
if (.object_begin != try source.next()) return error.UnexpectedToken;
var r: T = undefined;
var fields_seen: [structInfo.fields.len]bool = @splat(false);
var fields_seen: [structInfo.field_names.len]bool = @splat(false);
while (true) {
var name_token: ?Token = try source.nextAllocMax(allocator, .alloc_if_needed, options.max_value_len.?);
@@ -348,9 +348,14 @@ pub fn innerParse(
},
};
inline for (structInfo.fields, 0..) |field, i| {
if (field.is_comptime) @compileError("comptime fields are not supported: " ++ @typeName(T) ++ "." ++ field.name);
if (std.mem.eql(u8, field.name, field_name)) {
inline for (
structInfo.field_names,
structInfo.field_types,
structInfo.field_attrs,
0..,
) |f_name, f_type, f_attrs, i| {
if (f_attrs.@"comptime") @compileError("comptime fields are not supported: " ++ @typeName(T) ++ "." ++ f_name);
if (std.mem.eql(u8, f_name, field_name)) {
// Free the name token now in case we're using an allocator that optimizes freeing the last allocated object.
// (Recursing into innerParse() might trigger more allocations.)
freeAllocated(allocator, name_token.?);
@@ -360,14 +365,14 @@ pub fn innerParse(
.use_first => {
// Parse and ignore the redundant value.
// We don't want to skip the value, because we want type checking.
_ = try innerParse(field.type, allocator, source, options);
_ = try innerParse(f_type, allocator, source, options);
break;
},
.@"error" => return error.DuplicateField,
.use_last => {},
}
}
@field(r, field.name) = try innerParse(field.type, allocator, source, options);
@field(r, f_name) = try innerParse(f_type, allocator, source, options);
fields_seen[i] = true;
break;
}
@@ -493,7 +498,7 @@ pub fn innerParse(
_ = try source.allocNextIntoArrayList(&value_list, .alloc_always);
return try value_list.toOwnedSliceSentinel(s);
}
if (ptrInfo.is_const) {
if (ptrInfo.attrs.@"const") {
switch (try source.nextAllocMax(allocator, options.allocate.?, options.max_value_len.?)) {
inline .string, .allocated_string => |slice| return slice,
else => unreachable,
@@ -613,16 +618,16 @@ pub fn innerParseFromValue(
const kv = it.next().?;
const field_name = kv.key_ptr.*;
inline for (unionInfo.fields) |u_field| {
if (std.mem.eql(u8, u_field.name, field_name)) {
if (u_field.type == void) {
inline for (unionInfo.field_names, unionInfo.field_types) |u_field_name, u_field_type| {
if (std.mem.eql(u8, u_field_name, field_name)) {
if (u_field_type == void) {
// void isn't really a json type, but we can support void payload union tags with {} as a value.
if (kv.value_ptr.* != .object) return error.UnexpectedToken;
if (kv.value_ptr.*.object.count() != 0) return error.UnexpectedToken;
return @unionInit(T, u_field.name, {});
return @unionInit(T, u_field_name, {});
}
// Recurse.
return @unionInit(T, u_field.name, try innerParseFromValue(u_field.type, allocator, kv.value_ptr.*, options));
return @unionInit(T, u_field_name, try innerParseFromValue(u_field_type, allocator, kv.value_ptr.*, options));
}
}
// Didn't match anything.
@@ -632,11 +637,11 @@ pub fn innerParseFromValue(
.@"struct" => |structInfo| {
if (structInfo.is_tuple) {
if (source != .array) return error.UnexpectedToken;
if (source.array.items.len != structInfo.fields.len) return error.UnexpectedToken;
if (source.array.items.len != structInfo.field_names.len) return error.UnexpectedToken;
var r: T = undefined;
inline for (0..structInfo.fields.len, source.array.items) |i, item| {
r[i] = try innerParseFromValue(structInfo.fields[i].type, allocator, item, options);
inline for (0..structInfo.field_names.len, source.array.items) |i, item| {
r[i] = try innerParseFromValue(structInfo.field_types[i], allocator, item, options);
}
return r;
@@ -649,17 +654,22 @@ pub fn innerParseFromValue(
if (source != .object) return error.UnexpectedToken;
var r: T = undefined;
var fields_seen: [structInfo.fields.len]bool = @splat(false);
var fields_seen: [structInfo.field_names.len]bool = @splat(false);
var it = source.object.iterator();
while (it.next()) |kv| {
const field_name = kv.key_ptr.*;
inline for (structInfo.fields, 0..) |field, i| {
if (field.is_comptime) @compileError("comptime fields are not supported: " ++ @typeName(T) ++ "." ++ field.name);
if (std.mem.eql(u8, field.name, field_name)) {
inline for (
structInfo.field_names,
structInfo.field_types,
structInfo.field_attrs,
0..,
) |f_name, f_type, f_attrs, i| {
if (f_attrs.@"comptime") @compileError("comptime fields are not supported: " ++ @typeName(T) ++ "." ++ f_name);
if (std.mem.eql(u8, f_name, field_name)) {
assert(!fields_seen[i]); // Can't have duplicate keys in a Value.object.
@field(r, field.name) = try innerParseFromValue(field.type, allocator, kv.value_ptr.*, options);
@field(r, f_name) = try innerParseFromValue(f_type, allocator, kv.value_ptr.*, options);
fields_seen[i] = true;
break;
}
@@ -782,11 +792,17 @@ fn sliceToEnum(comptime T: type, slice: []const u8) !T {
return std.enums.fromInt(T, n) orelse return error.InvalidEnumTag;
}
fn fillDefaultStructValues(comptime T: type, r: *T, fields_seen: *[@typeInfo(T).@"struct".fields.len]bool) !void {
inline for (@typeInfo(T).@"struct".fields, 0..) |field, i| {
fn fillDefaultStructValues(comptime T: type, r: *T, fields_seen: *[@typeInfo(T).@"struct".field_names.len]bool) !void {
const info = @typeInfo(T).@"struct";
inline for (
info.field_names,
info.field_types,
info.field_attrs,
0..,
) |field_name, field_type, field_attrs, i| {
if (!fields_seen[i]) {
if (field.defaultValue()) |default| {
@field(r, field.name) = default;
if (field_attrs.defaultValue(field_type)) |default| {
@field(r, field_name) = default;
} else {
return error.MissingField;
}
+68 -100
View File
@@ -596,13 +596,8 @@ pub const Type = union(enum) {
/// therefore must be kept in sync with the compiler implementation.
pub const Pointer = struct {
size: Size,
is_const: bool,
is_volatile: bool,
/// `null` means implicit alignment, which is equivalent to `@alignOf(child)`.
alignment: ?usize,
address_space: AddressSpace,
attrs: Attributes,
child: type,
is_allowzero: bool,
/// The type of the sentinel is the element type of the pointer, which is
/// the value of the `child` field in this struct. However there is no way
@@ -665,46 +660,42 @@ pub const Type = union(enum) {
@"packed",
};
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const StructField = struct {
name: [:0]const u8,
type: type,
/// The type of the default value is the type of this struct field, which
/// is the value of the `type` field in this struct. However there is no
/// way to refer to that type here, so we use `*const anyopaque`.
/// See also: `defaultValue`.
default_value_ptr: ?*const anyopaque,
is_comptime: bool,
/// `null` means the field alignment was not explicitly specified. The
/// field will still be aligned to at least `@alignOf` its `type`.
alignment: ?usize,
/// Loads the field's default value from `default_value_ptr`.
/// Returns `null` if the field has no default value.
pub inline fn defaultValue(comptime sf: StructField) ?sf.type {
const dp: *const sf.type = @ptrCast(@alignCast(sf.default_value_ptr orelse return null));
return dp.*;
}
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const Attributes = struct {
@"comptime": bool = false,
@"align": ?usize = null,
default_value_ptr: ?*const anyopaque = null,
};
};
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const Struct = struct {
layout: ContainerLayout,
/// Only valid if layout is .@"packed"
backing_integer: ?type = null,
fields: []const StructField,
decls: []const Declaration,
is_tuple: bool,
layout: ContainerLayout,
/// Always `null` if `layout != .@"packed"`.
backing_integer: ?type,
field_names: []const [:0]const u8,
/// Guaranteed to have the same length as `field_names`.
field_types: []const type,
/// Guaranteed to have the same length as `field_names`.
field_attrs: []const FieldAttributes,
decl_names: []const [:0]const u8,
pub const FieldAttributes = struct {
@"comptime": bool = false,
/// `null` means the field alignment is not explicitly specified. The field will still
/// be aligned to at least `@alignOf` the field type.
@"align": ?usize = null,
/// The type of the default value is the type of this struct field. However, that type
/// is not known here, so we use a type-erased pointer instead, which must be cast to
/// a pointer to the field type.
///
/// See also: `defaultValue`.
default_value_ptr: ?*const anyopaque = null,
/// Loads the field's default value from `default_value_ptr`.
/// `FieldType` must exactly match the corresponding element of `Struct.field_types`.
/// Returns `null` if the field has no default value.
pub inline fn defaultValue(comptime attrs: FieldAttributes, comptime FieldType: type) ?FieldType {
const dp: *const FieldType = @ptrCast(@alignCast(attrs.default_value_ptr orelse return null));
return dp.*;
}
};
};
/// This data structure is used by the Zig language code generation and
@@ -722,28 +713,21 @@ pub const Type = union(enum) {
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const Error = struct {
name: [:0]const u8,
};
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const ErrorSet = ?[]const Error;
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const EnumField = struct {
name: [:0]const u8,
value: comptime_int,
pub const ErrorSet = struct {
error_names: ?[]const [:0]const u8,
};
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const Enum = struct {
tag_type: type,
fields: []const EnumField,
decls: []const Declaration,
is_exhaustive: bool,
mode: Mode,
field_names: []const [:0]const u8,
/// Guaranteed to have the same length as `field_names`.
field_values: []const comptime_int,
decl_names: []const [:0]const u8,
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
@@ -752,55 +736,45 @@ pub const Type = union(enum) {
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const UnionField = struct {
name: [:0]const u8,
type: type,
/// `null` means the field alignment was not explicitly specified. The
/// field will still be aligned to at least `@alignOf` its `type`.
alignment: ?usize,
pub const Union = struct {
layout: ContainerLayout,
tag_type: ?type,
/// Always `null` if `layout != .@"packed"`.
backing_integer: ?type,
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const Attributes = struct {
field_names: []const [:0]const u8,
/// Guaranteed to have the same length as `field_names`.
field_types: []const type,
/// Guaranteed to have the same length as `field_names`.
field_attrs: []const FieldAttributes,
decl_names: []const [:0]const u8,
pub const FieldAttributes = struct {
/// `null` means the field alignment is not explicitly specified. The field will still
/// be aligned to at least `@alignOf` the field type.
@"align": ?usize = null,
};
};
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const Union = struct {
layout: ContainerLayout,
tag_type: ?type,
fields: []const UnionField,
decls: []const Declaration,
};
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const Fn = struct {
calling_convention: CallingConvention,
attrs: Attributes,
is_generic: bool,
is_var_args: bool,
/// TODO change the language spec to make this not optional.
/// `null` means the return type is generic, i.e. it depends on a function argument.
return_type: ?type,
params: []const Param,
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const Param = struct {
is_generic: bool,
is_noalias: bool,
type: ?type,
/// A `null` element represents either an `anytype` parameter, or a parameter with a generic
/// type, i.e. where the type depends on a previous function argument.
param_types: []const ?type,
/// Guaranteed to have the same length as `param_types`.
param_attrs: []const ParamAttributes,
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const Attributes = struct {
@"noalias": bool = false,
};
pub const ParamAttributes = struct {
@"noalias": bool = false,
};
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const Attributes = struct {
@"callconv": CallingConvention = .auto,
varargs: bool = false,
@@ -810,7 +784,7 @@ pub const Type = union(enum) {
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const Opaque = struct {
decls: []const Declaration,
decl_names: []const [:0]const u8,
};
/// This data structure is used by the Zig language code generation and
@@ -831,12 +805,6 @@ pub const Type = union(enum) {
len: comptime_int,
child: type,
};
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const Declaration = struct {
name: [:0]const u8,
};
};
/// This data structure is used by the Zig language code generation and
+2 -2
View File
@@ -1648,8 +1648,8 @@ pub const CompareOperator = enum {
}
test reverse {
inline for (@typeInfo(CompareOperator).@"enum".fields) |op_field| {
const op = @as(CompareOperator, @enumFromInt(op_field.value));
inline for (@typeInfo(CompareOperator).@"enum".field_values) |op_field_value| {
const op = @as(CompareOperator, @enumFromInt(op_field_value));
try testing.expect(compare(2, op, 3) == compare(3, op.reverse(), 2));
try testing.expect(compare(3, op, 3) == compare(3, op.reverse(), 3));
try testing.expect(compare(4, op, 3) == compare(3, op.reverse(), 4));
+86 -102
View File
@@ -297,9 +297,13 @@ pub fn zeroes(comptime T: type) T {
return item;
} else {
var structure: T = undefined;
inline for (struct_info.fields) |field| {
if (!field.is_comptime) {
@field(structure, field.name) = zeroes(field.type);
inline for (
struct_info.field_names,
struct_info.field_types,
struct_info.field_attrs,
) |field_name, field_type, field_attrs| {
if (!field_attrs.@"comptime") {
@field(structure, field_name) = zeroes(field_type);
}
}
return structure;
@@ -321,7 +325,7 @@ pub fn zeroes(comptime T: type) T {
return null;
},
.one, .many => {
if (ptr_info.is_allowzero) return @ptrFromInt(0);
if (ptr_info.attrs.@"allowzero") return @ptrFromInt(0);
@compileError("Only nullable and allowzero pointers can be set to zero.");
},
}
@@ -471,44 +475,49 @@ pub fn zeroInit(comptime T: type, init: anytype) T {
switch (@typeInfo(Init)) {
.@"struct" => |init_info| {
if (init_info.is_tuple) {
if (init_info.fields.len > struct_info.fields.len) {
if (init_info.field_names.len > struct_info.field_names.len) {
@compileError("Tuple initializer has more elements than there are fields in `" ++ @typeName(T) ++ "`");
}
} else {
inline for (init_info.fields) |field| {
if (!@hasField(T, field.name)) {
@compileError("Encountered an initializer for `" ++ field.name ++ "`, but it is not a field of " ++ @typeName(T));
inline for (init_info.field_names) |field_name| {
if (!@hasField(T, field_name)) {
@compileError("Encountered an initializer for `" ++ field_name ++ "`, but it is not a field of " ++ @typeName(T));
}
}
}
var value: T = if (struct_info.layout == .@"extern") zeroes(T) else undefined;
inline for (struct_info.fields, 0..) |field, i| {
if (field.is_comptime) {
inline for (
struct_info.field_names,
struct_info.field_types,
struct_info.field_attrs,
0..,
) |f_name, f_type, f_attr, i| {
if (f_attr.@"comptime") {
continue;
}
if (init_info.is_tuple and init_info.fields.len > i) {
@field(value, field.name) = @field(init, init_info.fields[i].name);
} else if (@hasField(@TypeOf(init), field.name)) {
switch (@typeInfo(field.type)) {
if (init_info.is_tuple and init_info.field_names.len > i) {
@field(value, f_name) = @field(init, init_info.field_names[i]);
} else if (@hasField(@TypeOf(init), f_name)) {
switch (@typeInfo(f_type)) {
.@"struct" => {
@field(value, field.name) = zeroInit(field.type, @field(init, field.name));
@field(value, f_name) = zeroInit(f_type, @field(init, f_name));
},
else => {
@field(value, field.name) = @field(init, field.name);
@field(value, f_name) = @field(init, f_name);
},
}
} else if (field.defaultValue()) |val| {
@field(value, field.name) = val;
} else if (f_attr.defaultValue(f_type)) |val| {
@field(value, f_name) = val;
} else {
switch (@typeInfo(field.type)) {
switch (@typeInfo(f_type)) {
.@"struct" => {
@field(value, field.name) = std.mem.zeroInit(field.type, .{});
@field(value, f_name) = std.mem.zeroInit(f_type, .{});
},
else => {
@field(value, field.name) = std.mem.zeroes(@TypeOf(@field(value, field.name)));
@field(value, f_name) = std.mem.zeroes(@TypeOf(@field(value, f_name)));
},
}
}
@@ -867,13 +876,9 @@ fn Span(comptime T: type) type {
.many => ptr_info.sentinel() orelse @compileError("invalid type given to std.mem.span: " ++ @typeName(T)),
.c => 0,
};
return @Pointer(.slice, .{
.@"const" = ptr_info.is_const,
.@"volatile" = ptr_info.is_volatile,
.@"allowzero" = ptr_info.is_allowzero and ptr_info.size != .c,
.@"align" = ptr_info.alignment,
.@"addrspace" = ptr_info.address_space,
}, ptr_info.child, new_sentinel);
var attrs = ptr_info.attrs;
attrs.@"allowzero" = attrs.@"allowzero" and ptr_info.size != .c;
return @Pointer(.slice, attrs, ptr_info.child, new_sentinel);
},
else => {},
}
@@ -933,13 +938,9 @@ fn SliceTo(comptime T: type, comptime end: std.meta.Elem(T)) type {
.many => if (std.meta.sentinel(T)) |s| s == end else true,
.c => true,
};
return @Pointer(.slice, .{
.@"const" = ptr_info.is_const,
.@"volatile" = ptr_info.is_volatile,
.@"allowzero" = ptr_info.is_allowzero and ptr_info.size != .c,
.@"align" = ptr_info.alignment,
.@"addrspace" = ptr_info.address_space,
}, Elem, if (have_sentinel) end else null);
var attrs = ptr_info.attrs;
attrs.@"allowzero" = attrs.@"allowzero" and ptr_info.size != .c;
return @Pointer(.slice, attrs, Elem, if (have_sentinel) end else null);
},
else => {},
}
@@ -2210,19 +2211,19 @@ pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *a
.@"struct" => |struct_info| {
if (struct_info.backing_integer) |Int| {
ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*))));
} else inline for (std.meta.fields(S)) |f| {
switch (@typeInfo(f.type)) {
.@"struct" => byteSwapAllFieldsAligned(f.type, .fromByteUnits(f.alignment orelse @alignOf(f.type)), &@field(ptr, f.name)),
.@"union", .array => byteSwapAllFieldsAligned(f.type, .fromByteUnits(f.alignment orelse @alignOf(f.type)), &@field(ptr, f.name)),
} else inline for (struct_info.field_types, struct_info.field_names, struct_info.field_attrs) |f_type, f_name, f_attr| {
switch (@typeInfo(f_type)) {
.@"struct" => byteSwapAllFieldsAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)),
.@"union", .array => byteSwapAllFieldsAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)),
.@"enum" => {
@field(ptr, f.name) = @enumFromInt(@byteSwap(@intFromEnum(@field(ptr, f.name))));
@field(ptr, f_name) = @enumFromInt(@byteSwap(@intFromEnum(@field(ptr, f_name))));
},
.bool => {},
.float => |float_info| {
@field(ptr, f.name) = @bitCast(@byteSwap(@as(@Int(.unsigned, float_info.bits), @bitCast(@field(ptr, f.name)))));
@field(ptr, f_name) = @bitCast(@byteSwap(@as(@Int(.unsigned, float_info.bits), @bitCast(@field(ptr, f_name)))));
},
else => {
@field(ptr, f.name) = @byteSwap(@field(ptr, f.name));
@field(ptr, f_name) = @byteSwap(@field(ptr, f_name));
},
}
}
@@ -2232,9 +2233,9 @@ pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *a
@compileError("byteSwapAllFields expects an untagged union");
}
const first_size = @bitSizeOf(union_info.fields[0].type);
inline for (union_info.fields) |field| {
if (@bitSizeOf(field.type) != first_size) {
const first_size = @bitSizeOf(union_info.field_types[0]);
inline for (union_info.field_types) |field_type| {
if (@bitSizeOf(field_type) != first_size) {
@compileError("Unable to byte-swap unions with varying field sizes");
}
}
@@ -3940,15 +3941,8 @@ pub fn ReverseIterator(comptime T: type) type {
.many, .c => @compileError("expected slice or pointer to array, found '" ++ @typeName(T) ++ "'"),
}
const Element = std.meta.Elem(T);
const attrs: std.builtin.Type.Pointer.Attributes = .{
.@"const" = ptr.is_const,
.@"volatile" = ptr.is_volatile,
.@"allowzero" = ptr.is_allowzero,
.@"align" = ptr.alignment,
.@"addrspace" = ptr.address_space,
};
const Pointer = @Pointer(.many, attrs, Element, std.meta.sentinel(T));
const ElementPointer = @Pointer(.one, attrs, Element, null);
const Pointer = @Pointer(.many, ptr.attrs, Element, std.meta.sentinel(T));
const ElementPointer = @Pointer(.one, ptr.attrs, Element, null);
return struct {
ptr: Pointer,
index: usize,
@@ -4255,7 +4249,7 @@ pub fn alignPointerOffset(ptr: anytype, align_to: usize) ?usize {
@compileError("expected many item pointer, got " ++ @typeName(T));
// Do nothing if the pointer is already well-aligned.
if (align_to <= info.pointer.alignment orelse @alignOf(info.pointer.child))
if (align_to <= info.pointer.attrs.@"align" orelse @alignOf(info.pointer.child))
return 0;
// Calculate the aligned base address with an eye out for overflow.
@@ -4309,17 +4303,14 @@ fn CopyPtrAttrs(
comptime child: type,
) type {
const ptr = @typeInfo(source).pointer;
return @Pointer(size, .{
.@"const" = ptr.is_const,
.@"volatile" = ptr.is_volatile,
.@"allowzero" = ptr.is_allowzero,
.@"align" = ptr.alignment orelse a: {
// If the new child is aligned differently than the old one, explicitly align the type.
const want = @alignOf(ptr.child);
break :a if (@alignOf(child) == want) null else want;
},
.@"addrspace" = ptr.address_space,
}, child, null);
var attrs = ptr.attrs;
if (attrs.@"align" == null) {
const want = @alignOf(ptr.child);
if (@alignOf(child) != want) {
attrs.@"align" = want;
}
}
return @Pointer(size, attrs, child, null);
}
fn AsBytesReturnType(comptime P: type) type {
@@ -4383,10 +4374,13 @@ test "asBytes preserves pointer attributes" {
const in = @typeInfo(@TypeOf(inPtr)).pointer;
const out = @typeInfo(@TypeOf(outSlice)).pointer;
try testing.expectEqual(in.is_const, out.is_const);
try testing.expectEqual(in.is_volatile, out.is_volatile);
try testing.expectEqual(in.is_allowzero, out.is_allowzero);
try testing.expectEqual(in.alignment, out.alignment);
const in_attrs = in.attrs;
const out_attrs = out.attrs;
try testing.expectEqual(in_attrs.@"const", out_attrs.@"const");
try testing.expectEqual(in_attrs.@"volatile", out_attrs.@"volatile");
try testing.expectEqual(in_attrs.@"allowzero", out_attrs.@"allowzero");
try testing.expectEqual(in_attrs.@"align", out_attrs.@"align");
}
/// Given any value, returns a copy of its bytes in an array.
@@ -4463,13 +4457,13 @@ test "bytesAsValue preserves pointer attributes" {
const inSlice = @as(*align(16) const volatile [4]u8, @ptrCast(&inArr))[0..];
const outPtr = bytesAsValue(u32, inSlice);
const in = @typeInfo(@TypeOf(inSlice)).pointer;
const out = @typeInfo(@TypeOf(outPtr)).pointer;
const in_attrs = @typeInfo(@TypeOf(inSlice)).pointer.attrs;
const out_attrs = @typeInfo(@TypeOf(outPtr)).pointer.attrs;
try testing.expectEqual(in.is_const, out.is_const);
try testing.expectEqual(in.is_volatile, out.is_volatile);
try testing.expectEqual(in.is_allowzero, out.is_allowzero);
try testing.expectEqual(in.alignment, out.alignment);
try testing.expectEqual(in_attrs.@"const", out_attrs.@"const");
try testing.expectEqual(in_attrs.@"volatile", out_attrs.@"volatile");
try testing.expectEqual(in_attrs.@"allowzero", out_attrs.@"allowzero");
try testing.expectEqual(in_attrs.@"align", out_attrs.@"align");
}
/// Given a pointer to an array of bytes, returns a value of the specified type backed by a
@@ -4566,13 +4560,13 @@ test "bytesAsSlice preserves pointer attributes" {
const inSlice = @as(*align(16) const volatile [4]u8, @ptrCast(&inArr))[0..];
const outSlice = bytesAsSlice(u16, inSlice);
const in = @typeInfo(@TypeOf(inSlice)).pointer;
const out = @typeInfo(@TypeOf(outSlice)).pointer;
const in_attrs = @typeInfo(@TypeOf(inSlice)).pointer.attrs;
const out_attrs = @typeInfo(@TypeOf(outSlice)).pointer.attrs;
try testing.expectEqual(in.is_const, out.is_const);
try testing.expectEqual(in.is_volatile, out.is_volatile);
try testing.expectEqual(in.is_allowzero, out.is_allowzero);
try testing.expectEqual(in.alignment, out.alignment);
try testing.expectEqual(in_attrs.@"const", out_attrs.@"const");
try testing.expectEqual(in_attrs.@"volatile", out_attrs.@"volatile");
try testing.expectEqual(in_attrs.@"allowzero", out_attrs.@"allowzero");
try testing.expectEqual(in_attrs.@"align", out_attrs.@"align");
}
test "bytesAsSlice with zero-bit element type" {
@@ -4678,25 +4672,19 @@ test "sliceAsBytes preserves pointer attributes" {
const inSlice = @as(*align(16) const volatile [2]u16, @ptrCast(&inArr))[0..];
const outSlice = sliceAsBytes(inSlice);
const in = @typeInfo(@TypeOf(inSlice)).pointer;
const out = @typeInfo(@TypeOf(outSlice)).pointer;
const in_attrs = @typeInfo(@TypeOf(inSlice)).pointer.attrs;
const out_attrs = @typeInfo(@TypeOf(outSlice)).pointer.attrs;
try testing.expectEqual(in.is_const, out.is_const);
try testing.expectEqual(in.is_volatile, out.is_volatile);
try testing.expectEqual(in.is_allowzero, out.is_allowzero);
try testing.expectEqual(in.alignment, out.alignment);
try testing.expectEqual(in_attrs.@"const", out_attrs.@"const");
try testing.expectEqual(in_attrs.@"volatile", out_attrs.@"volatile");
try testing.expectEqual(in_attrs.@"allowzero", out_attrs.@"allowzero");
try testing.expectEqual(in_attrs.@"align", out_attrs.@"align");
}
fn AbsorbSentinelReturnType(comptime Slice: type) type {
const info = @typeInfo(Slice).pointer;
assert(info.size == .slice);
return @Pointer(.slice, .{
.@"const" = info.is_const,
.@"volatile" = info.is_volatile,
.@"allowzero" = info.is_allowzero,
.@"addrspace" = info.address_space,
.@"align" = info.alignment,
}, info.child, null);
return @Pointer(.slice, info.attrs, info.child, null);
}
/// If the provided slice is not sentinel terminated, do nothing and return that slice.
@@ -4949,13 +4937,9 @@ test "freeing empty string with null-terminated sentinel" {
/// all other pointer attributes copied from `AttributeSource`.
fn AlignedSlice(comptime AttributeSource: type, comptime new_alignment: usize) type {
const ptr = @typeInfo(AttributeSource).pointer;
return @Pointer(.slice, .{
.@"const" = ptr.is_const,
.@"volatile" = ptr.is_volatile,
.@"allowzero" = ptr.is_allowzero,
.@"align" = new_alignment,
.@"addrspace" = ptr.address_space,
}, ptr.child, null);
var attrs = ptr.attrs;
attrs.@"align" = new_alignment;
return @Pointer(.slice, attrs, ptr.child, null);
}
/// Returns the largest slice in the given bytes that conforms to the new alignment,
+9 -9
View File
@@ -183,7 +183,7 @@ pub fn destroy(self: Allocator, ptr: anytype) void {
const non_const_ptr = @as([*]u8, @ptrCast(@constCast(ptr)));
self.rawFree(
non_const_ptr[0..@sizeOf(T)],
.fromByteUnits(info.alignment orelse @alignOf(T)),
.fromByteUnits(info.attrs.@"align" orelse @alignOf(T)),
@returnAddress(),
);
}
@@ -331,7 +331,7 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
const new_len_bytes = math.mul(usize, @sizeOf(T), new_len) catch return false;
return self.rawResize(
old_memory,
.fromByteUnits(slice_info.alignment orelse @alignOf(T)),
.fromByteUnits(slice_info.attrs.@"align" orelse @alignOf(T)),
new_len_bytes,
@returnAddress(),
);
@@ -377,7 +377,7 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?@TypeOf(allo
const new_len_bytes = math.mul(usize, @sizeOf(T), new_len) catch return null;
const new_ptr = self.rawRemap(
old_memory,
.fromByteUnits(slice_info.alignment orelse @alignOf(T)),
.fromByteUnits(slice_info.attrs.@"align" orelse @alignOf(T)),
new_len_bytes,
@returnAddress(),
) orelse return null;
@@ -412,11 +412,11 @@ pub fn reallocAdvanced(
comptime assert(slice_info.size == .slice);
const T = slice_info.child;
if (old_mem.len == 0) {
return self.allocAdvancedWithRetAddr(T, .fromByteUnitsOptional(slice_info.alignment), new_n, return_address);
return self.allocAdvancedWithRetAddr(T, .fromByteUnitsOptional(slice_info.attrs.@"align"), new_n, return_address);
}
if (new_n == 0) {
self.free(old_mem);
const alignment = slice_info.alignment orelse @alignOf(T);
const alignment = slice_info.attrs.@"align" orelse @alignOf(T);
const addr = comptime std.mem.alignBackward(usize, math.maxInt(usize), alignment);
const ptr: *align(alignment) [0]T = @ptrFromInt(addr);
return ptr;
@@ -425,16 +425,16 @@ pub fn reallocAdvanced(
const old_byte_slice: []u8 = @ptrCast(@constCast(mem.absorbSentinel(old_mem)));
const byte_count = math.mul(usize, @sizeOf(T), new_n) catch return error.OutOfMemory;
// Note: can't set shrunk memory to undefined as memory shouldn't be modified on realloc failure
if (self.rawRemap(old_byte_slice, .fromByteUnits(slice_info.alignment orelse @alignOf(T)), byte_count, return_address)) |p| {
if (self.rawRemap(old_byte_slice, .fromByteUnits(slice_info.attrs.@"align" orelse @alignOf(T)), byte_count, return_address)) |p| {
return @ptrCast(@alignCast(p[0..byte_count]));
}
const new_mem = self.rawAlloc(byte_count, .fromByteUnits(slice_info.alignment orelse @alignOf(T)), return_address) orelse
const new_mem = self.rawAlloc(byte_count, .fromByteUnits(slice_info.attrs.@"align" orelse @alignOf(T)), return_address) orelse
return error.OutOfMemory;
const copy_len = @min(byte_count, old_byte_slice.len);
@memcpy(new_mem[0..copy_len], old_byte_slice[0..copy_len]);
@memset(old_byte_slice, undefined);
self.rawFree(old_byte_slice, .fromByteUnits(slice_info.alignment orelse @alignOf(T)), return_address);
self.rawFree(old_byte_slice, .fromByteUnits(slice_info.attrs.@"align" orelse @alignOf(T)), return_address);
return @ptrCast(@alignCast(new_mem[0..byte_count]));
}
@@ -448,7 +448,7 @@ pub fn free(self: Allocator, memory: anytype) void {
const bytes: []u8 = @ptrCast(@constCast(mem.absorbSentinel(memory)));
if (bytes.len == 0) return;
@memset(bytes, undefined);
self.rawFree(bytes, .fromByteUnits(slice_info.alignment orelse @alignOf(slice_info.child)), @returnAddress());
self.rawFree(bytes, .fromByteUnits(slice_info.attrs.@"align" orelse @alignOf(slice_info.child)), @returnAddress());
}
/// Copies `m` to newly allocated memory. Caller owns the memory.
+133 -173
View File
@@ -8,7 +8,7 @@ const root = @import("root");
pub const TrailerFlags = @import("meta/trailer_flags.zig").TrailerFlags;
const Type = std.builtin.Type;
const Type = std.lang.Type;
test {
_ = TrailerFlags;
@@ -22,21 +22,21 @@ pub fn stringToEnum(comptime T: type, str: []const u8) ?T {
// TODO The '100' here is arbitrary and should be increased when possible:
// - https://github.com/ziglang/zig/issues/4055
// - https://github.com/ziglang/zig/issues/3863
if (@typeInfo(T).@"enum".fields.len <= 100) {
if (@typeInfo(T).@"enum".field_names.len <= 100) {
const kvs = comptime build_kvs: {
const EnumKV = struct { []const u8, T };
var kvs_array: [@typeInfo(T).@"enum".fields.len]EnumKV = undefined;
for (@typeInfo(T).@"enum".fields, 0..) |enumField, i| {
kvs_array[i] = .{ enumField.name, @field(T, enumField.name) };
var kvs_array: [@typeInfo(T).@"enum".field_names.len]EnumKV = undefined;
for (@typeInfo(T).@"enum".field_names, 0..) |name, i| {
kvs_array[i] = .{ name, @field(T, name) };
}
break :build_kvs kvs_array[0..];
};
const map = std.StaticStringMap(T).initComptime(kvs);
return map.get(str);
} else {
inline for (@typeInfo(T).@"enum".fields) |enumField| {
if (mem.eql(u8, str, enumField.name)) {
return @field(T, enumField.name);
inline for (@typeInfo(T).@"enum".field_names) |name| {
if (mem.eql(u8, str, name)) {
return @field(T, name);
}
}
return null;
@@ -63,7 +63,7 @@ pub fn alignment(comptime T: type) comptime_int {
.pointer, .@"fn" => alignment(info.child),
else => @alignOf(T),
},
.pointer => |info| info.alignment orelse @alignOf(info.child),
.pointer => |info| info.attrs.@"align" orelse @alignOf(info.child),
else => @alignOf(T),
};
}
@@ -171,34 +171,20 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
switch (@typeInfo(T)) {
.pointer => |info| switch (info.size) {
.one => switch (@typeInfo(info.child)) {
.array => |array_info| return @Pointer(.one, .{
.@"const" = info.is_const,
.@"volatile" = info.is_volatile,
.@"allowzero" = info.is_allowzero,
.@"align" = info.alignment,
.@"addrspace" = info.address_space,
}, [array_info.len:sentinel_val]array_info.child, null),
.array => |array_info| return @Pointer(
.one,
info.attrs,
[array_info.len:sentinel_val]array_info.child,
null,
),
else => {},
},
.many, .slice => |size| return @Pointer(size, .{
.@"const" = info.is_const,
.@"volatile" = info.is_volatile,
.@"allowzero" = info.is_allowzero,
.@"align" = info.alignment,
.@"addrspace" = info.address_space,
}, info.child, sentinel_val),
.many, .slice => |size| return @Pointer(size, info.attrs, info.child, sentinel_val),
else => {},
},
.optional => |info| switch (@typeInfo(info.child)) {
.pointer => |ptr_info| switch (ptr_info.size) {
.many => return ?@Pointer(.many, .{
.@"const" = ptr_info.is_const,
.@"volatile" = ptr_info.is_volatile,
.@"allowzero" = ptr_info.is_allowzero,
.@"align" = ptr_info.alignment,
.@"addrspace" = ptr_info.address_space,
.child = ptr_info.child,
}, ptr_info.child, sentinel_val),
.many => return ?@Pointer(.many, ptr_info.attrs, ptr_info.child, sentinel_val),
else => {},
},
else => {},
@@ -238,14 +224,14 @@ test containerLayout {
try testing.expect(containerLayout(U3) == .@"extern");
}
/// Instead of this function, prefer to use e.g. `@typeInfo(foo).@"struct".decls`
/// Instead of this function, prefer to use e.g. `@typeInfo(foo).@"struct".decl_names`
/// directly when you know what kind of type it is.
pub fn declarations(comptime T: type) []const Type.Declaration {
pub fn declarations(comptime T: type) []const [:0]const u8 {
return switch (@typeInfo(T)) {
.@"struct" => |info| info.decls,
.@"enum" => |info| info.decls,
.@"union" => |info| info.decls,
.@"opaque" => |info| info.decls,
.@"struct" => |info| info.decl_names,
.@"enum" => |info| info.decl_names,
.@"union" => |info| info.decl_names,
.@"opaque" => |info| info.decl_names,
else => @compileError("Expected struct, enum, union, or opaque type, found '" ++ @typeName(T) ++ "'"),
};
}
@@ -268,7 +254,7 @@ test declarations {
pub fn a() void {}
};
const decls = comptime [_][]const Type.Declaration{
const decls = comptime [_][]const [:0]const u8{
declarations(E1),
declarations(S1),
declarations(U1),
@@ -277,97 +263,41 @@ test declarations {
inline for (decls) |decl| {
try testing.expect(decl.len == 1);
try testing.expect(comptime mem.eql(u8, decl[0].name, "a"));
try testing.expect(comptime mem.eql(u8, decl[0], "a"));
}
}
pub fn declarationInfo(comptime T: type, comptime decl_name: []const u8) Type.Declaration {
inline for (comptime declarations(T)) |decl| {
if (comptime mem.eql(u8, decl.name, decl_name))
return decl;
}
@compileError("'" ++ @typeName(T) ++ "' has no declaration '" ++ decl_name ++ "'");
}
test declarationInfo {
const E1 = enum {
A,
pub fn a() void {}
};
const S1 = struct {
pub fn a() void {}
};
const U1 = union {
b: u8,
pub fn a() void {}
};
const infos = comptime [_]Type.Declaration{
declarationInfo(E1, "a"),
declarationInfo(S1, "a"),
declarationInfo(U1, "a"),
};
inline for (infos) |info| {
try testing.expect(comptime mem.eql(u8, info.name, "a"));
}
}
pub inline fn fields(comptime T: type) switch (@typeInfo(T)) {
.@"struct" => []const Type.StructField,
.@"union" => []const Type.UnionField,
.@"enum" => []const Type.EnumField,
.error_set => []const Type.Error,
else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"),
} {
return switch (@typeInfo(T)) {
.@"struct" => |info| info.fields,
.@"union" => |info| info.fields,
.@"enum" => |info| info.fields,
.error_set => |errors| errors.?, // must be non global error set
else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"),
};
}
test fields {
const E1 = enum {
A,
};
const E2 = error{A};
const S1 = struct {
a: u8,
};
const U1 = union {
a: u8,
};
const e1f = comptime fields(E1);
const e2f = comptime fields(E2);
const sf = comptime fields(S1);
const uf = comptime fields(U1);
try testing.expect(e1f.len == 1);
try testing.expect(e2f.len == 1);
try testing.expect(sf.len == 1);
try testing.expect(uf.len == 1);
try testing.expect(mem.eql(u8, e1f[0].name, "A"));
try testing.expect(mem.eql(u8, e2f[0].name, "A"));
try testing.expect(mem.eql(u8, sf[0].name, "a"));
try testing.expect(mem.eql(u8, uf[0].name, "a"));
try testing.expect(comptime sf[0].type == u8);
try testing.expect(comptime uf[0].type == u8);
}
/// To be removed after Zig 0.17.0 is tagged.
pub const declarationInfo = @compileError("Deprecated; use '@hasDecl' instead");
/// To be removed after Zig 0.17.0 is tagged.
pub const fields = @compileError("Deprecated; use 'fieldNames' and 'fieldTypes' instead");
pub fn fieldInfo(comptime T: type, comptime field: FieldEnum(T)) switch (@typeInfo(T)) {
.@"struct" => Type.StructField,
.@"union" => Type.UnionField,
.@"enum" => Type.EnumField,
.error_set => Type.Error,
.@"struct" => struct { name: [:0]const u8, type: type, attrs: Type.Struct.FieldAttributes },
.@"union" => struct { name: [:0]const u8, type: type, attrs: Type.Union.FieldAttributes },
.@"enum" => struct { name: [:0]const u8, value: comptime_int },
.error_set => struct { name: [:0]const u8 },
else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"),
} {
return fields(T)[@intFromEnum(field)];
const idx = @intFromEnum(field);
return switch (@typeInfo(T)) {
.@"struct" => |info| .{
.name = info.field_names[idx],
.type = info.field_types[idx],
.attrs = info.field_attrs[idx],
},
.@"union" => |info| .{
.name = info.field_names[idx],
.type = info.field_types[idx],
.attrs = info.field_attrs[idx],
},
.@"enum" => |info| .{
.name = info.field_names[idx],
.value = info.field_values[idx],
},
.error_set => |info| .{ .name = info.error_names.?[idx] },
else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"),
};
}
test fieldInfo {
@@ -395,13 +325,13 @@ test fieldInfo {
try testing.expect(comptime uf.type == u8);
}
pub fn fieldNames(comptime T: type) *const [fields(T).len][:0]const u8 {
return comptime blk: {
const fieldInfos = fields(T);
var names: [fieldInfos.len][:0]const u8 = undefined;
for (&names, fieldInfos) |*name, field| name.* = field.name;
const final = names;
break :blk &final;
pub fn fieldNames(comptime T: type) []const [:0]const u8 {
return switch (@typeInfo(T)) {
.@"struct" => |s| s.field_names,
.@"union" => |u| u.field_names,
.@"enum" => |e| e.field_names,
.error_set => |es| es.error_names.?,
else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"),
};
}
@@ -433,14 +363,41 @@ test fieldNames {
try testing.expectEqualSlices(u8, u1names[1], "b");
}
pub fn fieldTypes(comptime T: type) []const type {
return switch (@typeInfo(T)) {
.@"struct" => |s| s.field_types,
.@"union" => |u| u.field_types,
else => @compileError("Expected struct or union type, found '" ++ @typeName(T) ++ "'"),
};
}
test fieldTypes {
const S1 = struct {
a: u8,
};
const U1 = union {
a: u8,
b: void,
};
const s1types = comptime fieldTypes(S1);
const u1types = comptime fieldTypes(U1);
try testing.expect(s1types.len == 1);
try testing.expect(s1types[0] == u8);
try testing.expect(u1types.len == 2);
try testing.expect(u1types[0] == u8);
try testing.expect(u1types[1] == void);
}
/// Given an enum or error set type, returns a pointer to an array containing all tags for that
/// enum or error set.
pub fn tags(comptime T: type) *const [fields(T).len]T {
pub fn tags(comptime T: type) *const [fieldNames(T).len]T {
return comptime blk: {
const fieldInfos = fields(T);
var res: [fieldInfos.len]T = undefined;
for (fieldInfos, 0..) |field, i| {
res[i] = @field(T, field.name);
const field_names = fieldNames(T);
var res: [field_names.len]T = undefined;
for (field_names, 0..) |field_name, i| {
res[i] = @field(T, field_name);
}
const final = res;
break :blk &final;
@@ -491,27 +448,30 @@ fn expectEqualEnum(expected: anytype, actual: @TypeOf(expected)) !void {
// because the language does not guarantee that the slice pointers for field names
// and decl names will be the same.
comptime {
const expected_fields = @typeInfo(expected).@"enum".fields;
const actual_fields = @typeInfo(actual).@"enum".fields;
if (expected_fields.len != actual_fields.len) return error.FailedTest;
for (expected_fields, 0..) |expected_field, i| {
const actual_field = actual_fields[i];
try testing.expectEqual(expected_field.value, actual_field.value);
try testing.expectEqualStrings(expected_field.name, actual_field.name);
const expected_field_names = @typeInfo(expected).@"enum".field_names;
const expected_field_values = @typeInfo(expected).@"enum".field_values;
const actual_field_names = @typeInfo(actual).@"enum".field_names;
const actual_field_values = @typeInfo(actual).@"enum".field_values;
if (expected_field_names.len != actual_field_names.len) return error.FailedTest;
for (expected_field_names, expected_field_values, 0..) |expected_field_name, expected_field_value, i| {
const actual_field_name = actual_field_names[i];
const actual_field_value = actual_field_values[i];
try testing.expectEqual(expected_field_value, actual_field_value);
try testing.expectEqualStrings(expected_field_name, actual_field_name);
}
}
comptime {
const expected_decls = @typeInfo(expected).@"enum".decls;
const actual_decls = @typeInfo(actual).@"enum".decls;
if (expected_decls.len != actual_decls.len) return error.FailedTest;
for (expected_decls, 0..) |expected_decl, i| {
const actual_decl = actual_decls[i];
try testing.expectEqualStrings(expected_decl.name, actual_decl.name);
const expected_decl_names = @typeInfo(expected).@"enum".decl_names;
const actual_decl_names = @typeInfo(actual).@"enum".decl_names;
if (expected_decl_names.len != actual_decl_names.len) return error.FailedTest;
for (expected_decl_names, 0..) |expected_decl_name, i| {
const actual_decl_name = actual_decl_names[i];
try testing.expectEqualStrings(expected_decl_name, actual_decl_name);
}
}
try testing.expectEqual(
@typeInfo(expected).@"enum".is_exhaustive,
@typeInfo(actual).@"enum".is_exhaustive,
@typeInfo(expected).@"enum".mode,
@typeInfo(actual).@"enum".mode,
);
}
@@ -534,11 +494,9 @@ test FieldEnum {
}
pub fn DeclEnum(comptime T: type) type {
const decls = declarations(T);
var names: [decls.len][]const u8 = undefined;
for (&names, decls) |*name, decl| name.* = decl.name;
const IntTag = std.math.IntFittingRange(0, decls.len -| 1);
return @Enum(IntTag, .exhaustive, &names, &std.simd.iota(IntTag, decls.len));
const decl_names = declarations(T);
const IntTag = std.math.IntFittingRange(0, decl_names.len -| 1);
return @Enum(IntTag, .exhaustive, decl_names, &std.simd.iota(IntTag, decl_names.len));
}
test DeclEnum {
@@ -622,8 +580,8 @@ pub fn eql(a: anytype, b: @TypeOf(a)) bool {
.@"struct" => |info| {
if (info.layout == .@"packed") return a == b;
inline for (info.fields) |field_info| {
if (!eql(@field(a, field_info.name), @field(b, field_info.name))) return false;
inline for (info.field_names) |field_name| {
if (!eql(@field(a, field_name), @field(b, field_name))) return false;
}
return true;
},
@@ -744,8 +702,8 @@ test eql {
/// Given a type and a name, return the field index according to source order.
/// Returns `null` if the field is not found.
pub fn fieldIndex(comptime T: type, comptime name: []const u8) ?comptime_int {
inline for (fields(T), 0..) |field, i| {
if (mem.eql(u8, field.name, name))
inline for (fieldNames(T), 0..) |field_name, i| {
if (mem.eql(u8, field_name, name))
return i;
}
return null;
@@ -782,12 +740,12 @@ pub fn ArgsTuple(comptime Function: type) type {
@compileError("ArgsTuple expects a function type");
const function_info = info.@"fn";
if (function_info.is_var_args)
if (function_info.attrs.varargs)
@compileError("Cannot create ArgsTuple for variadic function");
var argument_field_list: [function_info.params.len]type = undefined;
inline for (function_info.params, 0..) |arg, i| {
const T = arg.type orelse @compileError("cannot create ArgsTuple for function with an 'anytype' parameter");
var argument_field_list: [function_info.param_types.len]type = undefined;
inline for (function_info.param_types, 0..) |arg_type, i| {
const T = arg_type orelse @compileError("cannot create ArgsTuple for function with an 'anytype' parameter");
argument_field_list[i] = T;
}
@@ -807,13 +765,15 @@ const TupleTester = struct {
if (!info.@"struct".is_tuple)
@compileError("Struct type must be a tuple type");
const fields_list = std.meta.fields(Actual);
if (expected.len != fields_list.len)
@compileError("Argument count mismatch");
const field_names = info.@"struct".field_names;
if (expected.len != field_names.len) {
const msg = std.fmt.comptimePrint("Argument count mismatch: expected {d}, got {d}", .{ expected.len, field_names.len });
@compileError(msg);
}
inline for (fields_list, 0..) |fld, i| {
if (expected[i] != fld.type) {
@compileError("Field " ++ fld.name ++ " expected to be type " ++ @typeName(expected[i]) ++ ", but was type " ++ @typeName(fld.type));
inline for (field_names, info.@"struct".field_types, 0..) |fld_name, fld_type, i| {
if (expected[i] != fld_type) {
@compileError("Field " ++ fld_name ++ " expected to be type " ++ @typeName(expected[i]) ++ ", but was type " ++ @typeName(fld_type));
}
}
}
@@ -943,7 +903,7 @@ pub inline fn hasUniqueRepresentation(comptime T: type) bool {
.pointer => |info| info.size != .slice,
.optional => |info| switch (@typeInfo(info.child)) {
.pointer => |ptr| !ptr.is_allowzero and switch (ptr.size) {
.pointer => |ptr| !ptr.attrs.@"allowzero" and switch (ptr.size) {
.slice, .c => false,
.one, .many => true,
},
@@ -957,10 +917,10 @@ pub inline fn hasUniqueRepresentation(comptime T: type) bool {
var sum_size = @as(usize, 0);
inline for (info.fields) |field| {
if (field.is_comptime) continue;
if (!hasUniqueRepresentation(field.type)) return false;
sum_size += @sizeOf(field.type);
inline for (info.field_attrs, info.field_types) |field_attr, field_type| {
if (field_attr.@"comptime") continue;
if (!hasUniqueRepresentation(field_type)) return false;
sum_size += @sizeOf(field_type);
}
return @sizeOf(T) == sum_size;
+26 -19
View File
@@ -14,7 +14,7 @@ pub fn TrailerFlags(comptime Fields: type) type {
bits: Int,
pub const Int = @Int(.unsigned, bit_count);
pub const bit_count = @typeInfo(Fields).@"struct".fields.len;
pub const bit_count = @typeInfo(Fields).@"struct".field_names.len;
pub const FieldEnum = std.meta.FieldEnum(Fields);
@@ -22,11 +22,18 @@ pub fn TrailerFlags(comptime Fields: type) type {
pub const FieldValues = blk: {
var field_names: [bit_count][]const u8 = undefined;
var field_types: [bit_count]type = undefined;
var field_attrs: [bit_count]std.builtin.Type.StructField.Attributes = undefined;
for (@typeInfo(Fields).@"struct".fields, &field_names, &field_types, &field_attrs) |field, *new_name, *NewType, *new_attrs| {
new_name.* = field.name;
NewType.* = ?field.type;
const default: ?field.type = null;
var field_attrs: [bit_count]std.builtin.Type.Struct.FieldAttributes = undefined;
const fields_info = @typeInfo(Fields).@"struct";
for (
fields_info.field_names,
fields_info.field_types,
&field_names,
&field_types,
&field_attrs,
) |field_name, field_type, *new_name, *NewType, *new_attrs| {
new_name.* = field_name;
NewType.* = ?field_type;
const default: ?field_type = null;
new_attrs.* = .{ .default_value_ptr = &default };
}
break :blk @Struct(.auto, null, &field_names, &field_types, &field_attrs);
@@ -53,8 +60,8 @@ pub fn TrailerFlags(comptime Fields: type) type {
/// `fields` is a boolean struct where each active field is set to `true`
pub fn init(fields: ActiveFields) Self {
var self: Self = .{ .bits = 0 };
inline for (@typeInfo(Fields).@"struct".fields, 0..) |field, i| {
if (@field(fields, field.name))
inline for (@typeInfo(Fields).@"struct".field_names, 0..) |field_name, i| {
if (@field(fields, field_name))
self.bits |= 1 << i;
}
return self;
@@ -62,8 +69,8 @@ pub fn TrailerFlags(comptime Fields: type) type {
/// `fields` is a struct with each field set to an optional value
pub fn setMany(self: Self, p: [*]align(@alignOf(Fields)) u8, fields: FieldValues) void {
inline for (@typeInfo(Fields).@"struct".fields, 0..) |field, i| {
if (@field(fields, field.name)) |value|
inline for (@typeInfo(Fields).@"struct".field_names, 0..) |field_name, i| {
if (@field(fields, field_name)) |value|
self.set(p, @as(FieldEnum, @enumFromInt(i)), value);
}
}
@@ -93,30 +100,30 @@ pub fn TrailerFlags(comptime Fields: type) type {
pub fn offset(self: Self, comptime field: FieldEnum) usize {
var off: usize = 0;
inline for (@typeInfo(Fields).@"struct".fields, 0..) |field_info, i| {
inline for (@typeInfo(Fields).@"struct".field_types, 0..) |field_type, i| {
const active = (self.bits & (1 << i)) != 0;
if (i == @intFromEnum(field)) {
assert(active);
return mem.alignForward(usize, off, @alignOf(field_info.type));
return mem.alignForward(usize, off, @alignOf(field_type));
} else if (active) {
off = mem.alignForward(usize, off, @alignOf(field_info.type));
off += @sizeOf(field_info.type);
off = mem.alignForward(usize, off, @alignOf(field_type));
off += @sizeOf(field_type);
}
}
}
pub fn Field(comptime field: FieldEnum) type {
return @typeInfo(Fields).@"struct".fields[@intFromEnum(field)].type;
return @typeInfo(Fields).@"struct".field_types[@intFromEnum(field)];
}
pub fn sizeInBytes(self: Self) usize {
var off: usize = 0;
inline for (@typeInfo(Fields).@"struct".fields, 0..) |field, i| {
if (@sizeOf(field.type) == 0)
inline for (@typeInfo(Fields).@"struct".field_types, 0..) |field_type, i| {
if (@sizeOf(field_type) == 0)
continue;
if ((self.bits & (1 << i)) != 0) {
off = mem.alignForward(usize, off, @alignOf(field.type));
off += @sizeOf(field.type);
off = mem.alignForward(usize, off, @alignOf(field_type));
off += @sizeOf(field_type);
}
}
return off;
+49 -57
View File
@@ -44,17 +44,7 @@ pub fn MultiArrayList(comptime T: type) type {
const Elem = switch (@typeInfo(T)) {
.@"struct" => T,
.@"union" => |u| struct {
pub const Bare = Bare: {
var field_names: [u.fields.len][]const u8 = undefined;
var field_types: [u.fields.len]type = undefined;
var field_attrs: [u.fields.len]std.builtin.Type.UnionField.Attributes = undefined;
for (u.fields, &field_names, &field_types, &field_attrs) |field, *name, *Type, *attrs| {
name.* = field.name;
Type.* = field.type;
attrs.* = .{ .@"align" = field.alignment };
}
break :Bare @Union(u.layout, null, &field_names, &field_types, &field_attrs);
};
pub const Bare = @Union(u.layout, null, u.field_names, u.field_types[0..], u.field_attrs[0..]);
pub const Tag =
u.tag_type orelse @compileError("MultiArrayList does not support untagged unions");
tags: Tag,
@@ -87,7 +77,7 @@ pub fn MultiArrayList(comptime T: type) type {
pub const Slice = struct {
/// This array is indexed by the field index which can be obtained
/// by using @intFromEnum() on the Field enum
ptrs: [fields.len][*]u8,
ptrs: [field_names.len][*]u8,
len: usize,
capacity: usize,
@@ -116,15 +106,15 @@ pub fn MultiArrayList(comptime T: type) type {
.@"union" => Elem.fromT(elem),
else => unreachable,
};
inline for (fields, 0..) |field_info, i| {
self.items(@as(Field, @enumFromInt(i)))[index] = @field(e, field_info.name);
inline for (field_names, 0..) |field_name, i| {
self.items(@as(Field, @enumFromInt(i)))[index] = @field(e, field_name);
}
}
pub fn get(self: Slice, index: usize) T {
var result: Elem = undefined;
inline for (fields, 0..) |field_info, i| {
@field(result, field_info.name) = self.items(@as(Field, @enumFromInt(i)))[index];
inline for (field_names, 0..) |field_name, i| {
@field(result, field_name) = self.items(@as(Field, @enumFromInt(i)))[index];
}
return switch (@typeInfo(T)) {
.@"struct" => result,
@@ -134,9 +124,9 @@ pub fn MultiArrayList(comptime T: type) type {
}
pub fn swap(self: Slice, a: usize, b: usize) void {
inline for (@typeInfo(Field).@"enum".fields) |field| {
const its = self.items(@field(Field, field.name));
std.mem.swap(@FieldType(T, field.name), &its[a], &its[b]);
inline for (@typeInfo(Field).@"enum".field_names) |field_name| {
const its = self.items(@field(Field, field_name));
std.mem.swap(@FieldType(T, field_name), &its[a], &its[b]);
}
}
@@ -162,9 +152,9 @@ pub fn MultiArrayList(comptime T: type) type {
/// Asserts that `off + len <= s.len`.
pub fn subslice(s: Slice, off: usize, len: usize) Slice {
assert(off + len <= s.len);
var ptrs: [fields.len][*]u8 = undefined;
inline for (s.ptrs, &ptrs, fields) |in, *out, field| {
out.* = in + (off * @sizeOf(field.type));
var ptrs: [field_names.len][*]u8 = undefined;
inline for (s.ptrs, &ptrs, field_types) |in, *out, field_type| {
out.* = in + (off * @sizeOf(field_type));
}
return .{
.ptrs = ptrs,
@@ -185,7 +175,9 @@ pub fn MultiArrayList(comptime T: type) type {
const Self = @This();
const fields = meta.fields(Elem);
const field_names = @typeInfo(Elem).@"struct".field_names;
const field_types = @typeInfo(Elem).@"struct".field_types;
const field_attrs = @typeInfo(Elem).@"struct".field_attrs;
/// `sizes.bytes` is an array of @sizeOf each T field. Sorted by alignment, descending.
/// `sizes.fields` is an array mapping from `sizes.bytes` array index to field index.
/// `sizes.big_align` is the overall alignment of the allocation, which equals the maximum field alignment.
@@ -195,13 +187,13 @@ pub fn MultiArrayList(comptime T: type) type {
size_index: usize,
alignment: usize,
};
var data: [fields.len]Data = undefined;
var data: [field_names.len]Data = undefined;
var big_align: usize = 1;
for (fields, 0..) |field_info, i| {
for (field_types, field_attrs, 0..) |f_type, f_attrs, i| {
data[i] = .{
.size = @sizeOf(field_info.type),
.size = @sizeOf(f_type),
.size_index = i,
.alignment = field_info.alignment orelse @alignOf(field_info.type),
.alignment = f_attrs.@"align" orelse @alignOf(f_type),
};
big_align = @max(big_align, data[i].alignment);
}
@@ -211,10 +203,10 @@ pub fn MultiArrayList(comptime T: type) type {
return lhs.alignment > rhs.alignment;
}
};
@setEvalBranchQuota(3 * fields.len * std.math.log2(fields.len));
@setEvalBranchQuota(3 * field_names.len * std.math.log2(field_names.len));
mem.sort(Data, &data, {}, Sort.lessThan);
var sizes_bytes: [fields.len]usize = undefined;
var field_indexes: [fields.len]usize = undefined;
var sizes_bytes: [field_names.len]usize = undefined;
var field_indexes: [field_names.len]usize = undefined;
for (data, 0..) |elem, i| {
sizes_bytes[i] = elem.size;
field_indexes[i] = elem.size_index;
@@ -368,13 +360,13 @@ pub fn MultiArrayList(comptime T: type) type {
else => unreachable,
};
const slices = self.slice();
inline for (fields, 0..) |field_info, field_index| {
inline for (field_names, 0..) |field_name, field_index| {
const field_slice = slices.items(@as(Field, @enumFromInt(field_index)));
var i: usize = self.len - 1;
while (i > index) : (i -= 1) {
field_slice[i] = field_slice[i - 1];
}
field_slice[index] = @field(entry, field_info.name);
field_slice[index] = @field(entry, field_name);
}
}
@@ -394,7 +386,7 @@ pub fn MultiArrayList(comptime T: type) type {
/// retain list ordering.
pub fn swapRemove(self: *Self, index: usize) void {
const slices = self.slice();
inline for (fields, 0..) |_, i| {
inline for (field_names, 0..) |_, i| {
const field_slice = slices.items(@as(Field, @enumFromInt(i)));
field_slice[index] = field_slice[self.len - 1];
field_slice[self.len - 1] = undefined;
@@ -406,7 +398,7 @@ pub fn MultiArrayList(comptime T: type) type {
/// after it to preserve order.
pub fn orderedRemove(self: *Self, index: usize) void {
const slices = self.slice();
inline for (fields, 0..) |_, field_index| {
inline for (field_names, 0..) |_, field_index| {
const field_slice = slices.items(@as(Field, @enumFromInt(field_index)));
var i = index;
while (i < self.len - 1) : (i += 1) {
@@ -437,7 +429,7 @@ pub fn MultiArrayList(comptime T: type) type {
if (removed == end) continue; // allows duplicates in `sorted_indexes`
const start = removed + 1;
const len = end - start; // safety checks `sorted_indexes` are sorted
inline for (fields, 0..) |_, field_index| {
inline for (field_names, 0..) |_, field_index| {
const field_slice = slices.items(@enumFromInt(field_index));
@memmove(field_slice[start - shift ..][0..len], field_slice[start..][0..len]); // safety checks initial `sorted_indexes` are in range
}
@@ -446,7 +438,7 @@ pub fn MultiArrayList(comptime T: type) type {
const start = sorted_indexes[sorted_indexes.len - 1] + 1;
const end = self.len;
const len = end - start; // safety checks final `sorted_indexes` are in range
inline for (fields, 0..) |_, field_index| {
inline for (field_names, 0..) |_, field_index| {
const field_slice = slices.items(@enumFromInt(field_index));
@memmove(field_slice[start - shift ..][0..len], field_slice[start..][0..len]);
}
@@ -471,8 +463,8 @@ pub fn MultiArrayList(comptime T: type) type {
const other_bytes = gpa.alignedAlloc(u8, sizes.big_align, capacityInBytes(new_len)) catch {
const self_slice = self.slice();
inline for (fields, 0..) |field_info, i| {
if (@sizeOf(field_info.type) != 0) {
inline for (field_types, 0..) |field_type, i| {
if (@sizeOf(field_type) != 0) {
const field = @as(Field, @enumFromInt(i));
const dest_slice = self_slice.items(field)[new_len..];
// We use memset here for more efficient codegen in safety-checked,
@@ -492,8 +484,8 @@ pub fn MultiArrayList(comptime T: type) type {
self.len = new_len;
const self_slice = self.slice();
const other_slice = other.slice();
inline for (fields, 0..) |field_info, i| {
if (@sizeOf(field_info.type) != 0) {
inline for (field_types, 0..) |field_type, i| {
if (@sizeOf(field_type) != 0) {
const field = @as(Field, @enumFromInt(i));
@memcpy(other_slice.items(field), self_slice.items(field));
}
@@ -529,7 +521,7 @@ pub fn MultiArrayList(comptime T: type) type {
const init_capacity: comptime_int = init: {
var max: comptime_int = 1;
for (fields) |field| max = @max(max, @sizeOf(field.type));
for (field_types) |field_type| max = @max(max, @sizeOf(field_type));
break :init @max(1, std.atomic.cache_line / max);
};
@@ -564,8 +556,8 @@ pub fn MultiArrayList(comptime T: type) type {
};
const self_slice = self.slice();
const other_slice = other.slice();
inline for (fields, 0..) |field_info, i| {
if (@sizeOf(field_info.type) != 0) {
inline for (field_types, 0..) |field_type, i| {
if (@sizeOf(field_type) != 0) {
const field = @as(Field, @enumFromInt(i));
@memcpy(other_slice.items(field), self_slice.items(field));
}
@@ -583,8 +575,8 @@ pub fn MultiArrayList(comptime T: type) type {
result.len = self.len;
const self_slice = self.slice();
const result_slice = result.slice();
inline for (fields, 0..) |field_info, i| {
if (@sizeOf(field_info.type) != 0) {
inline for (field_types, 0..) |field_type, i| {
if (@sizeOf(field_type) != 0) {
const field = @as(Field, @enumFromInt(i));
@memcpy(result_slice.items(field), self_slice.items(field));
}
@@ -600,11 +592,11 @@ pub fn MultiArrayList(comptime T: type) type {
slice: Slice,
pub fn swap(sc: @This(), a_index: usize, b_index: usize) void {
inline for (fields, 0..) |field_info, i| {
if (@sizeOf(field_info.type) != 0) {
inline for (field_types, 0..) |field_type, i| {
if (@sizeOf(field_type) != 0) {
const field: Field = @enumFromInt(i);
const ptr = sc.slice.items(field);
mem.swap(field_info.type, &ptr[a_index], &ptr[b_index]);
mem.swap(field_type, &ptr[a_index], &ptr[b_index]);
}
}
}
@@ -676,18 +668,18 @@ pub fn MultiArrayList(comptime T: type) type {
}
const Entry = entry: {
var field_names: [fields.len][]const u8 = undefined;
var field_types: [fields.len]type = undefined;
var field_attrs: [fields.len]std.builtin.Type.StructField.Attributes = undefined;
for (sizes.fields, &field_names, &field_types, &field_attrs) |i, *name, *Type, *attrs| {
name.* = fields[i].name ++ "_ptr";
Type.* = *fields[i].type;
var entry_field_names: [field_names.len][]const u8 = undefined;
var entry_field_types: [field_names.len]type = undefined;
var entry_field_attrs: [field_names.len]std.builtin.Type.Struct.FieldAttributes = undefined;
for (sizes.fields, &entry_field_names, &entry_field_types, &entry_field_attrs) |i, *name, *Type, *attrs| {
name.* = field_names[i] ++ "_ptr";
Type.* = *field_types[i];
attrs.* = .{
.@"comptime" = fields[i].is_comptime,
.@"align" = fields[i].alignment,
.@"comptime" = field_attrs[i].@"comptime",
.@"align" = field_attrs[i].@"align",
};
}
break :entry @Struct(.@"extern", null, &field_names, &field_types, &field_attrs);
break :entry @Struct(.@"extern", null, &entry_field_names, &entry_field_types, &entry_field_attrs);
};
/// This function is used in the debugger pretty formatters in tools/ to fetch the
/// child field order and entry type to facilitate fancy debug printing for this type.
+8 -7
View File
@@ -82,16 +82,17 @@ pub const DevicePath = extern struct {
}
pub fn getDevicePath(self: *const DevicePath) ?uefi.DevicePath {
inline for (@typeInfo(uefi.DevicePath).@"union".fields) |ufield| {
const enum_value = std.meta.stringToEnum(uefi.DevicePath.Type, ufield.name);
const u_info = @typeInfo(uefi.DevicePath).@"union";
inline for (u_info.field_names, u_info.field_types) |ufield_name, ufield_type| {
const enum_value = std.meta.stringToEnum(uefi.DevicePath.Type, ufield_name);
// Got the associated union type for self.type, now
// we need to initialize it and its subtype
if (self.type == enum_value) {
const subtype = self.initSubtype(ufield.type);
const subtype = self.initSubtype(ufield_type);
if (subtype) |sb| {
// e.g. return .{ .hardware = .{ .pci = @ptrCast(...) } }
return @unionInit(uefi.DevicePath, ufield.name, sb);
return @unionInit(uefi.DevicePath, ufield_name, sb);
}
}
}
@@ -103,13 +104,13 @@ pub const DevicePath = extern struct {
const type_info = @typeInfo(TUnion).@"union";
const TTag = type_info.tag_type.?;
inline for (type_info.fields) |subtype| {
inline for (type_info.field_names, type_info.field_types) |subtype_name, subtype_type| {
// The tag names match the union names, so just grab that off the enum
const tag_val: u8 = @intFromEnum(@field(TTag, subtype.name));
const tag_val: u8 = @intFromEnum(@field(TTag, subtype_name));
if (self.subtype == tag_val) {
// e.g. expr = .{ .pci = @ptrCast(...) }
return @unionInit(TUnion, subtype.name, @as(subtype.type, @ptrCast(self)));
return @unionInit(TUnion, subtype_name, @as(subtype_type, @ptrCast(self)));
}
}
+1 -1
View File
@@ -1271,7 +1271,7 @@ fn ProtocolInterfaces(HandleType: type, Interfaces: type) type {
@compileError("expected tuple of protocol interfaces, got " ++ @typeName(Interfaces));
const interfaces_info = interfaces_type_info.@"struct";
var tuple_types: [interfaces_info.fields.len * 2 + 2]type = undefined;
var tuple_types: [interfaces_info.field_names.len * 2 + 2]type = undefined;
tuple_types[0] = HandleType;
tuple_types[tuple_types.len - 1] = ?*const Guid;
+9 -15
View File
@@ -144,7 +144,7 @@ pub const OBJECT = struct {
Session = 5,
_,
pub const Max: @typeInfo(@This()).@"enum".tag_type = @typeInfo(@This()).@"enum".fields.len;
pub const Max: @typeInfo(@This()).@"enum".tag_type = @typeInfo(@This()).@"enum".field_names.len;
};
pub const NAME_INFORMATION = extern struct {
@@ -575,7 +575,7 @@ pub const FILE = struct {
MupProvider = 83,
_,
pub const Maximum: @typeInfo(@This()).@"enum".tag_type = 1 + @typeInfo(@This()).@"enum".fields.len;
pub const Maximum: @typeInfo(@This()).@"enum".tag_type = 1 + @typeInfo(@This()).@"enum".field_names.len;
};
pub const BASIC_INFORMATION = extern struct {
@@ -881,7 +881,7 @@ pub const DIRECTORY = struct {
NotifyFull = 3,
_,
pub const Maximum: @typeInfo(@This()).@"enum".tag_type = 1 + @typeInfo(@This()).@"enum".fields.len;
pub const Maximum: @typeInfo(@This()).@"enum".tag_type = 1 + @typeInfo(@This()).@"enum".field_names.len;
};
};
@@ -930,14 +930,8 @@ pub const CONSOLE = struct {
pub const Tag = @typeInfo(WITH).@"union".tag_type.?;
pub const Payload = PAYLOAD: {
const with_fields = @typeInfo(WITH).@"union".fields;
var field_names: [with_fields.len][]const u8 = undefined;
var field_types: [with_fields.len]type = undefined;
for (with_fields, &field_names, &field_types) |field, *field_name, *field_type| {
field_name.* = field.name;
field_type.* = field.type;
}
break :PAYLOAD @Union(.@"extern", null, &field_names, &field_types, &@splat(.{}));
const with_info = @typeInfo(WITH).@"union";
break :PAYLOAD @Union(.@"extern", null, with_info.field_names, with_info.field_types[0..], &@splat(.{}));
};
};
};
@@ -2122,7 +2116,7 @@ pub const HEAP = opaque {
Custom,
_,
pub const Max: @typeInfo(@This()).@"enum".tag_type = @typeInfo(@This()).@"enum".fields.len;
pub const Max: @typeInfo(@This()).@"enum".tag_type = @typeInfo(@This()).@"enum".field_names.len;
};
pub const VA_CALLBACKS = extern struct {
@@ -3369,7 +3363,7 @@ pub const FS_INFORMATION_CLASS = enum(c_int) {
Guid = 15,
_,
pub const Maximum: @typeInfo(@This()).@"enum".tag_type = 1 + @typeInfo(@This()).@"enum".fields.len;
pub const Maximum: @typeInfo(@This()).@"enum".tag_type = 1 + @typeInfo(@This()).@"enum".field_names.len;
};
pub const SECTION_INHERIT = enum(c_int) {
@@ -3493,7 +3487,7 @@ pub const MEM = struct {
ImageMachine,
_,
pub const Max: @typeInfo(@This()).@"enum".tag_type = @typeInfo(@This()).@"enum".fields.len;
pub const Max: @typeInfo(@This()).@"enum".tag_type = @typeInfo(@This()).@"enum".field_names.len;
};
};
};
@@ -4467,7 +4461,7 @@ pub const KEY = struct {
Layer = 5,
_,
pub const Max: @typeInfo(@This()).@"enum".tag_type = @typeInfo(@This()).@"enum".fields.len;
pub const Max: @typeInfo(@This()).@"enum".tag_type = @typeInfo(@This()).@"enum".field_names.len;
};
pub const PARTIAL_INFORMATION = extern struct {
+2 -2
View File
@@ -332,8 +332,8 @@ test "fsync" {
test "getrlimit and setrlimit" {
if (posix.system.rlimit_resource == void) return error.SkipZigTest;
inline for (@typeInfo(posix.rlimit_resource).@"enum".fields) |field| {
const resource: posix.rlimit_resource = @enumFromInt(field.value);
inline for (@typeInfo(posix.rlimit_resource).@"enum".field_values) |field_value| {
const resource: posix.rlimit_resource = @enumFromInt(field_value);
const limit = try posix.getrlimit(resource);
// XNU kernel does not support RLIMIT_STACK if a custom stack is active,

Some files were not shown because too many files have changed in this diff Show More