authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-04-18 00:15:53+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-04-17 22:47:54-07:00
log21a6a1b0f2d7241594a9aa123e48cf2e3ebaccb9
tree106fe6c9dfc11e73b3b3f04e5cc43d93b3da4685
parent187f0c1e262cbeb37d72c571381b5b94c1eb3a63

Sema: cap depth of value printing in type names

Certain types (notably, `std.ComptimeStringMap`) were resulting in excessively long type names when instantiated, which in turn resulted in excessively long symbol names. These are problematic for two reasons: * Symbol names are sometimes read by humans -- they ought to be readable. * Some other applications (looking at you, xcode) trip on very long symbol names. To work around this for now, we cap the depth of value printing at 1, as opposed to the normal 3. This doesn't guarantee anything -- there could still be, for instance, an incredibly long aggregate -- but it works around the issue in practice for the time being.

3 files changed, 35 insertions(+), 19 deletions(-)

src/Sema.zig+27-17
......@@ -2869,14 +2869,14 @@ fn createAnonymousDeclTypeNamed(
28692869 anon_prefix: []const u8,
28702870 inst: ?Zir.Inst.Index,
28712871) !InternPool.DeclIndex {
2872 const mod = sema.mod;
2873 const ip = &mod.intern_pool;
2872 const zcu = sema.mod;
2873 const ip = &zcu.intern_pool;
28742874 const gpa = sema.gpa;
28752875 const namespace = block.namespace;
2876 const src_decl = mod.declPtr(block.src_decl);
2876 const src_decl = zcu.declPtr(block.src_decl);
28772877 const src_node = src_decl.relativeToNodeIndex(src.node_offset.x);
2878 const new_decl_index = try mod.allocateNewDecl(namespace, src_node);
2879 errdefer mod.destroyDecl(new_decl_index);
2878 const new_decl_index = try zcu.allocateNewDecl(namespace, src_node);
2879 errdefer zcu.destroyDecl(new_decl_index);
28802880
28812881 switch (name_strategy) {
28822882 .anon => {
......@@ -2887,15 +2887,15 @@ fn createAnonymousDeclTypeNamed(
28872887 // This name is also used as the key in the parent namespace so it cannot be
28882888 // renamed.
28892889
2890 const name = mod.intern_pool.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{
2891 src_decl.name.fmt(&mod.intern_pool), anon_prefix, @intFromEnum(new_decl_index),
2890 const name = ip.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{
2891 src_decl.name.fmt(ip), anon_prefix, @intFromEnum(new_decl_index),
28922892 }, .no_embedded_nulls) catch unreachable;
2893 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name);
2893 try zcu.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name);
28942894 return new_decl_index;
28952895 },
28962896 .parent => {
2897 const name = mod.declPtr(block.src_decl).name;
2898 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name);
2897 const name = zcu.declPtr(block.src_decl).name;
2898 try zcu.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name);
28992899 return new_decl_index;
29002900 },
29012901 .func => {
......@@ -2906,7 +2906,7 @@ fn createAnonymousDeclTypeNamed(
29062906 defer buf.deinit();
29072907
29082908 const writer = buf.writer();
2909 try writer.print("{}(", .{mod.declPtr(block.src_decl).name.fmt(&mod.intern_pool)});
2909 try writer.print("{}(", .{zcu.declPtr(block.src_decl).name.fmt(ip)});
29102910
29112911 var arg_i: usize = 0;
29122912 for (fn_info.param_body) |zir_inst| switch (zir_tags[@intFromEnum(zir_inst)]) {
......@@ -2921,7 +2921,17 @@ fn createAnonymousDeclTypeNamed(
29212921 return sema.createAnonymousDeclTypeNamed(block, src, val, .anon, anon_prefix, null);
29222922
29232923 if (arg_i != 0) try writer.writeByte(',');
2924 try writer.print("{}", .{arg_val.fmtValue(sema.mod, sema)});
2924
2925 // Limiting the depth here helps avoid type names getting too long, which
2926 // in turn helps to avoid unreasonably long symbol names for namespaced
2927 // symbols. Such names should ideally be human-readable, and additionally,
2928 // some tooling may not support very long symbol names.
2929 try writer.print("{}", .{Value.fmtValueFull(.{
2930 .val = arg_val,
2931 .mod = zcu,
2932 .opt_sema = sema,
2933 .depth = 1,
2934 })});
29252935
29262936 arg_i += 1;
29272937 continue;
......@@ -2930,8 +2940,8 @@ fn createAnonymousDeclTypeNamed(
29302940 };
29312941
29322942 try writer.writeByte(')');
2933 const name = try mod.intern_pool.getOrPutString(gpa, buf.items, .no_embedded_nulls);
2934 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name);
2943 const name = try ip.getOrPutString(gpa, buf.items, .no_embedded_nulls);
2944 try zcu.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name);
29352945 return new_decl_index;
29362946 },
29372947 .dbg_var => {
......@@ -2942,10 +2952,10 @@ fn createAnonymousDeclTypeNamed(
29422952 .dbg_var_ptr, .dbg_var_val => {
29432953 if (zir_data[i].str_op.operand != ref) continue;
29442954
2945 const name = try mod.intern_pool.getOrPutStringFmt(gpa, "{}.{s}", .{
2946 src_decl.name.fmt(&mod.intern_pool), zir_data[i].str_op.getStr(sema.code),
2955 const name = try ip.getOrPutStringFmt(gpa, "{}.{s}", .{
2956 src_decl.name.fmt(ip), zir_data[i].str_op.getStr(sema.code),
29472957 }, .no_embedded_nulls);
2948 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name);
2958 try zcu.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name);
29492959 return new_decl_index;
29502960 },
29512961 else => {},
src/Value.zig+5
......@@ -44,9 +44,14 @@ pub fn fmtValue(val: Value, mod: *Module, opt_sema: ?*Sema) std.fmt.Formatter(pr
4444 .val = val,
4545 .mod = mod,
4646 .opt_sema = opt_sema,
47 .depth = 3,
4748 } };
4849}
4950
51pub fn fmtValueFull(ctx: print_value.FormatContext) std.fmt.Formatter(print_value.format) {
52 return .{ .data = ctx };
53}
54
5055/// Converts `val` to a null-terminated string stored in the InternPool.
5156/// Asserts `val` is an array of `u8`
5257pub fn toIpString(val: Value, ty: Type, mod: *Module) !InternPool.NullTerminatedString {
src/print_value.zig+3-2
......@@ -14,10 +14,11 @@ const Target = std.Target;
1414const max_aggregate_items = 100;
1515const max_string_len = 256;
1616
17const FormatContext = struct {
17pub const FormatContext = struct {
1818 val: Value,
1919 mod: *Module,
2020 opt_sema: ?*Sema,
21 depth: u8,
2122};
2223
2324pub fn format(
......@@ -28,7 +29,7 @@ pub fn format(
2829) !void {
2930 _ = options;
3031 comptime std.debug.assert(fmt.len == 0);
31 return print(ctx.val, writer, 3, ctx.mod, ctx.opt_sema) catch |err| switch (err) {
32 return print(ctx.val, writer, ctx.depth, ctx.mod, ctx.opt_sema) catch |err| switch (err) {
3233 error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function
3334 error.ComptimeBreak, error.ComptimeReturn => unreachable,
3435 error.AnalysisFail, error.NeededSourceLocation => unreachable, // TODO: re-evaluate when we use `opt_sema` more fully