From 7826e28bd38876e253f5842f53177dd9f45caa9a Mon Sep 17 00:00:00 2001 From: r00ster91 Date: Thu, 8 Dec 2022 22:05:30 +0200 Subject: [PATCH 1/2] Re-apply: "std.ComptimeStringMap: use tuple types" 096d3efae5fcaa5640f4acb2f9be2d7f93f7fdb2 was not the cause of the CI failure. --- lib/std/comptime_string_map.zig | 49 ++++++++++++++------------------- lib/std/meta.zig | 10 ++----- 2 files changed, 22 insertions(+), 37 deletions(-) diff --git a/lib/std/comptime_string_map.zig b/lib/std/comptime_string_map.zig index 09ba4e5a3c..f7736413d5 100644 --- a/lib/std/comptime_string_map.zig +++ b/lib/std/comptime_string_map.zig @@ -5,9 +5,8 @@ const mem = std.mem; /// Works by separating the keys by length at comptime and only checking strings of /// equal length at runtime. /// -/// `kvs` expects a list literal containing list literals or an array/slice of structs -/// where `.@"0"` is the `[]const u8` key and `.@"1"` is the associated value of type `V`. -/// TODO: https://github.com/ziglang/zig/issues/4335 +/// `kvs_list` expects a list of `struct { []const u8, V }` (key-value pair) tuples. +/// You can pass `struct { []const u8 }` (only keys) tuples if `V` is `void`. pub fn ComptimeStringMap(comptime V: type, comptime kvs_list: anytype) type { const precomputed = comptime blk: { @setEvalBranchQuota(2000); @@ -97,32 +96,26 @@ test "ComptimeStringMap list literal of list literals" { } test "ComptimeStringMap array of structs" { - const KV = struct { - @"0": []const u8, - @"1": TestEnum, - }; + const KV = struct { []const u8, TestEnum }; const map = ComptimeStringMap(TestEnum, [_]KV{ - .{ .@"0" = "these", .@"1" = .D }, - .{ .@"0" = "have", .@"1" = .A }, - .{ .@"0" = "nothing", .@"1" = .B }, - .{ .@"0" = "incommon", .@"1" = .C }, - .{ .@"0" = "samelen", .@"1" = .E }, + .{ "these", .D }, + .{ "have", .A }, + .{ "nothing", .B }, + .{ "incommon", .C }, + .{ "samelen", .E }, }); try testMap(map); } test "ComptimeStringMap slice of structs" { - const KV = struct { - @"0": []const u8, - @"1": TestEnum, - }; + const KV = struct { []const u8, TestEnum }; const slice: []const KV = &[_]KV{ - .{ .@"0" = "these", .@"1" = .D }, - .{ .@"0" = "have", .@"1" = .A }, - .{ .@"0" = "nothing", .@"1" = .B }, - .{ .@"0" = "incommon", .@"1" = .C }, - .{ .@"0" = "samelen", .@"1" = .E }, + .{ "these", .D }, + .{ "have", .A }, + .{ "nothing", .B }, + .{ "incommon", .C }, + .{ "samelen", .E }, }; const map = ComptimeStringMap(TestEnum, slice); @@ -141,15 +134,13 @@ fn testMap(comptime map: anytype) !void { } test "ComptimeStringMap void value type, slice of structs" { - const KV = struct { - @"0": []const u8, - }; + const KV = struct { []const u8 }; const slice: []const KV = &[_]KV{ - .{ .@"0" = "these" }, - .{ .@"0" = "have" }, - .{ .@"0" = "nothing" }, - .{ .@"0" = "incommon" }, - .{ .@"0" = "samelen" }, + .{"these"}, + .{"have"}, + .{"nothing"}, + .{"incommon"}, + .{"samelen"}, }; const map = ComptimeStringMap(void, slice); diff --git a/lib/std/meta.zig b/lib/std/meta.zig index b2fd10107b..9dd1a97baf 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -115,16 +115,10 @@ pub fn stringToEnum(comptime T: type, str: []const u8) ?T { // - https://github.com/ziglang/zig/issues/3863 if (@typeInfo(T).Enum.fields.len <= 100) { const kvs = comptime build_kvs: { - // In order to generate an array of structs that play nice with anonymous - // list literals, we need to give them "0" and "1" field names. - // TODO https://github.com/ziglang/zig/issues/4335 - const EnumKV = struct { - @"0": []const u8, - @"1": T, - }; + const EnumKV = struct { []const u8, T }; var kvs_array: [@typeInfo(T).Enum.fields.len]EnumKV = undefined; inline for (@typeInfo(T).Enum.fields) |enumField, i| { - kvs_array[i] = .{ .@"0" = enumField.name, .@"1" = @field(T, enumField.name) }; + kvs_array[i] = .{ enumField.name, @field(T, enumField.name) }; } break :build_kvs kvs_array[0..]; }; From ee9fc54cd032b6ac0fcaa422aa9c2826fa370bfa Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 8 Dec 2022 22:21:49 +0200 Subject: [PATCH 2/2] TypedValue: fix handling of tuples represented as empty_struct_value --- src/TypedValue.zig | 16 ++++------------ src/type.zig | 1 - test/behavior.zig | 1 + test/behavior/bugs/13785.zig | 12 ++++++++++++ 4 files changed, 17 insertions(+), 13 deletions(-) create mode 100644 test/behavior/bugs/13785.zig diff --git a/src/TypedValue.zig b/src/TypedValue.zig index 10ab88b866..3c1972c78d 100644 --- a/src/TypedValue.zig +++ b/src/TypedValue.zig @@ -142,12 +142,10 @@ pub fn print( .extern_options_type => return writer.writeAll("std.builtin.ExternOptions"), .type_info_type => return writer.writeAll("std.builtin.Type"), - .empty_struct_value => return writer.writeAll(".{}"), - .aggregate => { + .empty_struct_value, .aggregate => { if (level == 0) { return writer.writeAll(".{ ... }"); } - const values = val.castTag(.aggregate).?; if (ty.zigTypeTag() == .Struct) { try writer.writeAll(".{"); const max_len = std.math.min(ty.structFieldCount(), max_aggregate_items); @@ -161,13 +159,7 @@ pub fn print( } try print(.{ .ty = ty.structFieldType(i), - .val = switch (ty.containerLayout()) { - .Packed => values.data[i], - else => ty.structFieldValueComptime(i) orelse b: { - const vals = values.data; - break :b vals[i]; - }, - }, + .val = val.fieldValue(ty, i), }, writer, level - 1, mod); } if (ty.structFieldCount() > max_aggregate_items) { @@ -184,7 +176,7 @@ pub fn print( var i: u32 = 0; while (i < max_len) : (i += 1) { - buf[i] = std.math.cast(u8, values.data[i].toUnsignedInt(target)) orelse break :str; + buf[i] = std.math.cast(u8, val.fieldValue(ty, i).toUnsignedInt(target)) orelse break :str; } const truncated = if (len > max_string_len) " (truncated)" else ""; @@ -199,7 +191,7 @@ pub fn print( if (i != 0) try writer.writeAll(", "); try print(.{ .ty = elem_ty, - .val = values.data[i], + .val = val.fieldValue(ty, i), }, writer, level - 1, mod); } if (len > max_aggregate_items) { diff --git a/src/type.zig b/src/type.zig index f587bdc490..1aefa8f7a1 100644 --- a/src/type.zig +++ b/src/type.zig @@ -5670,7 +5670,6 @@ pub const Type = extern union { switch (ty.tag()) { .@"struct" => { const struct_obj = ty.castTag(.@"struct").?.data; - assert(struct_obj.layout != .Packed); const field = struct_obj.fields.values()[index]; if (field.is_comptime) { return field.default_val; diff --git a/test/behavior.zig b/test/behavior.zig index 64ffcb7a44..e4a04bbccb 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -120,6 +120,7 @@ test { _ = @import("behavior/bugs/13435.zig"); _ = @import("behavior/bugs/13664.zig"); _ = @import("behavior/bugs/13714.zig"); + _ = @import("behavior/bugs/13785.zig"); _ = @import("behavior/byteswap.zig"); _ = @import("behavior/byval_arg_var.zig"); _ = @import("behavior/call.zig"); diff --git a/test/behavior/bugs/13785.zig b/test/behavior/bugs/13785.zig new file mode 100644 index 0000000000..cef117f486 --- /dev/null +++ b/test/behavior/bugs/13785.zig @@ -0,0 +1,12 @@ +const builtin = @import("builtin"); +const std = @import("std"); + +const S = packed struct { a: u0 = 0 }; +test { + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + + var a: u8 = 0; + try std.io.null_writer.print("\n{} {}\n", .{ a, S{} }); +}