authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-09-26 02:34:25+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-09-26 02:34:25+02:00
log08e1138080b40027595798572be1aad2600019f2
treec7e34dc78236924a8ab54c75c28a968ddfdab278
parent5a263ea6752da8736d00f00af5d2a75e69970259
parent50cf87f8fc01be98ec6f12ed954fbbcef0156a0d

Merge pull request 'maker: serialize compilation errors of configurer over the build protocol' (#36959) from bsp-configure-ftbfs into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36959

8 files changed, 65 insertions(+), 79 deletions(-)

lib/compiler/Maker.zig+8-2
...@@ -740,6 +740,9 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -740,6 +740,9 @@ pub fn main(init: process.Init.Minimal) !void {
740 var configure_source_files: Cache.Manifest.SelfContainedFiles = .empty;740 var configure_source_files: Cache.Manifest.SelfContainedFiles = .empty;
741 defer configure_source_files.deinit(gpa);741 defer configure_source_files.deinit(gpa);
742742
743 var configure_error_bundle: std.zig.ErrorBundle = .empty;
744 defer configure_error_bundle.deinit(gpa);
745
743 // If this fails, we can still start the server and wait for user746 // If this fails, we can still start the server and wait for user
744 // to request a rebuild. If it returns error.FailedButCacheIntact747 // to request a rebuild. If it returns error.FailedButCacheIntact
745 // we can even still do file system watching and automatically748 // we can even still do file system watching and automatically
...@@ -762,6 +765,7 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -762,6 +765,7 @@ pub fn main(init: process.Init.Minimal) !void {
762 .print_configuration = print_configuration,765 .print_configuration = print_configuration,
763 .forks = forks.items,766 .forks = forks.items,
764 .src_files = &configure_source_files,767 .src_files = &configure_source_files,
768 .error_bundle = if (protocol_server != null) &configure_error_bundle else null,
765 })) |scanned_config| {769 })) |scanned_config| {
766 if (help_menu) {770 if (help_menu) {
767 scanned_config.printUsage(&graph, initStdoutWriter(io)) catch |err| switch (err) {771 scanned_config.printUsage(&graph, initStdoutWriter(io)) catch |err| switch (err) {
...@@ -1048,8 +1052,8 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -1048,8 +1052,8 @@ pub fn main(init: process.Init.Minimal) !void {
1048 _ = io.lockStderr(&.{}, graph.stderr_mode) catch {};1052 _ = io.lockStderr(&.{}, graph.stderr_mode) catch {};
1049 process.exit(1);1053 process.exit(1);
1050 }1054 }
1051 if (protocol_server != null) {1055 if (protocol_server) |s| {
1052 fatal("(zig build system) TODO send error messages to client when build.zig compilation fails", .{});1056 try s.serveErrorBundle(.bsp_configuration_failed, configure_error_bundle);
1053 }1057 }
1054 if (watch_flag and can_fs_watch) {1058 if (watch_flag and can_fs_watch) {
1055 fatal("(zig build system) TODO set up fs watching even when build.zig compilation fails", .{});1059 fatal("(zig build system) TODO set up fs watching even when build.zig compilation fails", .{});
...@@ -1087,6 +1091,7 @@ const ConfigureOptions = struct {...@@ -1087,6 +1091,7 @@ const ConfigureOptions = struct {
1087 print_configuration: PrintConfiguration,1091 print_configuration: PrintConfiguration,
1088 forks: []Fork,1092 forks: []Fork,
1089 src_files: *Cache.Manifest.SelfContainedFiles,1093 src_files: *Cache.Manifest.SelfContainedFiles,
1094 error_bundle: ?*std.zig.ErrorBundle = null,
1090};1095};
10911096
1092fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {1097fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {
...@@ -1471,6 +1476,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {...@@ -1471,6 +1476,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {
1471 .arch_os_abi = target_arch_os_abi,1476 .arch_os_abi = target_arch_os_abi,
1472 .progress_node = compile_prog_node,1477 .progress_node = compile_prog_node,
1473 .skip_log_cmdline_on_compile_errors = !graph.verbose,1478 .skip_log_cmdline_on_compile_errors = !graph.verbose,
1479 .error_bundle = options.error_bundle,
1474 })) |r| r.path else |err| return err;1480 })) |r| r.path else |err| return err;
1475 defer gpa.free(configure_exe_path.sub_path);1481 defer gpa.free(configure_exe_path.sub_path);
14761482
lib/compiler/objcopy.zig+2-2
...@@ -234,9 +234,9 @@ fn cmdObjCopy(arena: Allocator, io: Io, args: []const []const u8) !void {...@@ -234,9 +234,9 @@ fn cmdObjCopy(arena: Allocator, io: Io, args: []const []const u8) !void {
234 // The build system already knows what the output is at this point, we234 // The build system already knows what the output is at this point, we
235 // only need to communicate that the process has finished.235 // only need to communicate that the process has finished.
236 // Use the empty error bundle to indicate that the update is done.236 // Use the empty error bundle to indicate that the update is done.
237 try server.serveErrorBundle(std.zig.ErrorBundle.empty);237 try server.serveErrorBundle(.error_bundle, std.zig.ErrorBundle.empty);
238 },238 },
239 else => fatal("unsupported message: {s}", .{@tagName(hdr.tag)}),239 else => fatal("unsupported message: {t}", .{hdr.tag}),
240 }240 }
241 }241 }
242 }242 }
lib/compiler/resinator/main.zig+4-4
...@@ -704,7 +704,7 @@ const ErrorHandler = union(enum) {...@@ -704,7 +704,7 @@ const ErrorHandler = union(enum) {
704 var error_bundle = try cliDiagnosticsToErrorBundle(allocator, diagnostics);704 var error_bundle = try cliDiagnosticsToErrorBundle(allocator, diagnostics);
705 defer error_bundle.deinit(allocator);705 defer error_bundle.deinit(allocator);
706706
707 try server.serveErrorBundle(error_bundle);707 try server.serveErrorBundle(.error_bundle, error_bundle);
708 },708 },
709 .stderr => return diagnostics.renderToStderr(io, args),709 .stderr => return diagnostics.renderToStderr(io, args),
710 }710 }
...@@ -726,7 +726,7 @@ const ErrorHandler = union(enum) {...@@ -726,7 +726,7 @@ const ErrorHandler = union(enum) {
726 );726 );
727 defer error_bundle.deinit(allocator);727 defer error_bundle.deinit(allocator);
728728
729 try server.serveErrorBundle(error_bundle);729 try server.serveErrorBundle(.error_bundle, error_bundle);
730 },730 },
731 .stderr => {731 .stderr => {
732 // aro errors have already been emitted732 // aro errors have already been emitted
...@@ -751,7 +751,7 @@ const ErrorHandler = union(enum) {...@@ -751,7 +751,7 @@ const ErrorHandler = union(enum) {
751 var error_bundle = try diagnosticsToErrorBundle(allocator, source, diagnostics, mappings);751 var error_bundle = try diagnosticsToErrorBundle(allocator, source, diagnostics, mappings);
752 defer error_bundle.deinit(allocator);752 defer error_bundle.deinit(allocator);
753753
754 try server.serveErrorBundle(error_bundle);754 try server.serveErrorBundle(.error_bundle, error_bundle);
755 },755 },
756 .stderr => return diagnostics.renderToStderr(io, cwd, source, mappings),756 .stderr => return diagnostics.renderToStderr(io, cwd, source, mappings),
757 }757 }
...@@ -773,7 +773,7 @@ const ErrorHandler = union(enum) {...@@ -773,7 +773,7 @@ const ErrorHandler = union(enum) {
773 var error_bundle = try errorStringToErrorBundle(allocator, format, args);773 var error_bundle = try errorStringToErrorBundle(allocator, format, args);
774 defer error_bundle.deinit(allocator);774 defer error_bundle.deinit(allocator);
775775
776 try server.serveErrorBundle(error_bundle);776 try server.serveErrorBundle(.error_bundle, error_bundle);
777 },777 },
778 .stderr => {778 .stderr => {
779 const stderr = try io.lockStderr(&.{}, null);779 const stderr = try io.lockStderr(&.{}, null);
lib/compiler/translate-c/main.zig+1-1
...@@ -105,7 +105,7 @@ fn serveErrorBundle(arena: std.mem.Allocator, io: Io, diagnostics: *const aro.Di...@@ -105,7 +105,7 @@ fn serveErrorBundle(arena: std.mem.Allocator, io: Io, diagnostics: *const aro.Di
105 .out = &stdout_writer.interface,105 .out = &stdout_writer.interface,
106 .in = undefined,106 .in = undefined,
107 };107 };
108 try server.serveErrorBundle(error_bundle);108 try server.serveErrorBundle(.error_bundle, error_bundle);
109}109}
110110
111pub const usage =111pub const usage =
lib/std/zig.zig+17-7
...@@ -1713,6 +1713,9 @@ pub const BuildExeSubprocessOptions = struct {...@@ -1713,6 +1713,9 @@ pub const BuildExeSubprocessOptions = struct {
1713 cpu_features: ?[]const u8 = null,1713 cpu_features: ?[]const u8 = null,
1714 progress_node: std.Progress.Node = .none,1714 progress_node: std.Progress.Node = .none,
1715 skip_log_cmdline_on_compile_errors: bool = false,1715 skip_log_cmdline_on_compile_errors: bool = false,
1716 /// If this is provided, compilation errors are sent here. Otherwise, they are printed to stderr.
1717 /// Must be an initialized `ErrorBundle`; if it is updated then it is cleared first.
1718 error_bundle: ?*ErrorBundle = null,
1716};1719};
17171720
1718pub const BuildExeSubprocessError = error{1721pub const BuildExeSubprocessError = error{
...@@ -1781,8 +1784,10 @@ pub fn buildExeSubprocess(...@@ -1781,8 +1784,10 @@ pub fn buildExeSubprocess(
1781 var result: ?Cache.Path = null;1784 var result: ?Cache.Path = null;
1782 defer if (result) |r| gpa.free(r.sub_path);1785 defer if (result) |r| gpa.free(r.sub_path);
17831786
1784 var result_error_bundle: ErrorBundle = .empty;1787 var default_error_bundle: ErrorBundle = .empty;
1785 defer result_error_bundle.deinit(gpa);1788 defer default_error_bundle.deinit(gpa);
1789
1790 const error_bundle = options.error_bundle orelse &default_error_bundle;
17861791
1787 var received_fs_inputs = false;1792 var received_fs_inputs = false;
1788 var cache_hit = false;1793 var cache_hit = false;
...@@ -1816,8 +1821,8 @@ pub fn buildExeSubprocess(...@@ -1816,8 +1821,8 @@ pub fn buildExeSubprocess(
1816 }1821 }
1817 },1822 },
1818 .error_bundle => {1823 .error_bundle => {
1819 result_error_bundle.deinit(gpa);1824 error_bundle.deinit(gpa);
1820 result_error_bundle = Server.allocErrorBundle(gpa, body) catch |err| switch (err) {1825 error_bundle.* = Server.allocErrorBundle(gpa, body) catch |err| switch (err) {
1821 error.EndOfStream => break,1826 error.EndOfStream => break,
1822 else => |e| return e,1827 else => |e| return e,
1823 };1828 };
...@@ -1884,8 +1889,8 @@ pub fn buildExeSubprocess(...@@ -1884,8 +1889,8 @@ pub fn buildExeSubprocess(
1884 return error.AlreadyReported;1889 return error.AlreadyReported;
1885 }1890 }
18861891
1887 if (result_error_bundle.errorMessageCount() > 0) {1892 if (default_error_bundle.errorMessageCount() > 0) {
1888 result_error_bundle.renderToStderr(io, .{}, .auto) catch |err| switch (err) {1893 default_error_bundle.renderToStderr(io, .{}, .auto) catch |err| switch (err) {
1889 error.Canceled => |e| return e,1894 error.Canceled => |e| return e,
1890 else => |e| {1895 else => |e| {
1891 log.err("failed rendering error bundle: {t}", .{e});1896 log.err("failed rendering error bundle: {t}", .{e});
...@@ -1893,12 +1898,17 @@ pub fn buildExeSubprocess(...@@ -1893,12 +1898,17 @@ pub fn buildExeSubprocess(
1893 },1898 },
1894 };1899 };
1895 if (!options.skip_log_cmdline_on_compile_errors) log.err("command reported {d} compilation errors: {f}", .{1900 if (!options.skip_log_cmdline_on_compile_errors) log.err("command reported {d} compilation errors: {f}", .{
1896 result_error_bundle.errorMessageCount(), cmd,1901 default_error_bundle.errorMessageCount(), cmd,
1897 });1902 });
1898 if (received_fs_inputs) return error.FailedButCacheIntact;1903 if (received_fs_inputs) return error.FailedButCacheIntact;
1899 return error.AlreadyReported;1904 return error.AlreadyReported;
1900 }1905 }
19011906
1907 if (error_bundle.errorMessageCount() > 0) {
1908 if (received_fs_inputs) return error.FailedButCacheIntact;
1909 return error.AlreadyReported;
1910 }
1911
1902 const base_path = result orelse {1912 const base_path = result orelse {
1903 log.err("command failed to report result: {f}", .{cmd});1913 log.err("command failed to report result: {f}", .{cmd});
1904 return error.AlreadyReported;1914 return error.AlreadyReported;
lib/std/zig/Server.zig+8-22
...@@ -83,6 +83,10 @@ pub const Message = struct {...@@ -83,6 +83,10 @@ pub const Message = struct {
83 /// Body is a cwd relative path to the configuration file.83 /// Body is a cwd relative path to the configuration file.
84 /// This message only applies to the build system protocol.84 /// This message only applies to the build system protocol.
85 bsp_configuration,85 bsp_configuration,
86 /// build.zig itself failed to build from source.
87 /// Body is an `ErrorBundle`
88 /// This message only applies to the build system protocol.
89 bsp_configuration_failed,
86 /// Does not have a body.90 /// Does not have a body.
87 /// This message only applies to the build system protocol.91 /// This message only applies to the build system protocol.
88 bsp_build_started,92 bsp_build_started,
...@@ -307,7 +311,7 @@ pub fn serveTestResults(s: *Server, msg: OutMessage.TestResults) !void {...@@ -307,7 +311,7 @@ pub fn serveTestResults(s: *Server, msg: OutMessage.TestResults) !void {
307 try s.out.flush();311 try s.out.flush();
308}312}
309313
310pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void {314pub fn serveErrorBundle(s: *Server, tag: Message.Tag, error_bundle: std.zig.ErrorBundle) !void {
311 const eb_hdr: OutMessage.ErrorBundle = .{315 const eb_hdr: OutMessage.ErrorBundle = .{
312 .extra_len = @intCast(error_bundle.extra.len),316 .extra_len = @intCast(error_bundle.extra.len),
313 .string_bytes_len = @intCast(error_bundle.string_bytes.len),317 .string_bytes_len = @intCast(error_bundle.string_bytes.len),
...@@ -315,7 +319,7 @@ pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void {...@@ -315,7 +319,7 @@ pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void {
315 const bytes_len = @sizeOf(OutMessage.ErrorBundle) +319 const bytes_len = @sizeOf(OutMessage.ErrorBundle) +
316 4 * error_bundle.extra.len + error_bundle.string_bytes.len;320 4 * error_bundle.extra.len + error_bundle.string_bytes.len;
317 try s.serveMessageHeader(.{321 try s.serveMessageHeader(.{
318 .tag = .error_bundle,322 .tag = tag,
319 .bytes_len = @intCast(bytes_len),323 .bytes_len = @intCast(bytes_len),
320 });324 });
321 try s.out.writeStruct(eb_hdr, .little);325 try s.out.writeStruct(eb_hdr, .little);
...@@ -327,31 +331,13 @@ pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void {...@@ -327,31 +331,13 @@ pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void {
327pub fn allocErrorBundle(gpa: Allocator, body: []const u8) error{ OutOfMemory, EndOfStream }!std.zig.ErrorBundle {331pub fn allocErrorBundle(gpa: Allocator, body: []const u8) error{ OutOfMemory, EndOfStream }!std.zig.ErrorBundle {
328 var r: Reader = .fixed(body);332 var r: Reader = .fixed(body);
329 const hdr = r.takeStruct(OutMessage.ErrorBundle, .little) catch |err| switch (err) {333 const hdr = r.takeStruct(OutMessage.ErrorBundle, .little) catch |err| switch (err) {
330 error.EndOfStream => |e| return e,
331 error.ReadFailed => unreachable,334 error.ReadFailed => unreachable,
332 };
333
334 var eb: std.zig.ErrorBundle = .{
335 .string_bytes = &.{},
336 .extra = &.{},
337 };
338 errdefer eb.deinit(gpa);
339
340 const extra = try gpa.alloc(u32, hdr.extra_len);
341 eb.extra = extra;
342 const string_bytes = try gpa.alloc(u8, hdr.string_bytes_len);
343 eb.string_bytes = string_bytes;
344
345 r.readSliceEndian(u32, extra, .little) catch |err| switch (err) {
346 error.EndOfStream => |e| return e,335 error.EndOfStream => |e| return e,
347 error.ReadFailed => unreachable,
348 };336 };
349 r.readSliceAll(string_bytes) catch |err| switch (err) {337 return std.zig.ErrorBundle.readAlloc(&r, gpa, hdr.extra_len, hdr.string_bytes_len) catch |err| switch (err) {
350 error.EndOfStream => |e| return e,
351 error.ReadFailed => unreachable,338 error.ReadFailed => unreachable,
339 else => |e| return e,
352 };340 };
353
354 return eb;
355}341}
356342
357pub const TestMetadata = struct {343pub const TestMetadata = struct {
src/main.zig+4-4
...@@ -4453,7 +4453,7 @@ fn serve(...@@ -4453,7 +4453,7 @@ fn serve(
4453 }4453 }
44544454
4455 if (output.errors.errorMessageCount() != 0) {4455 if (output.errors.errorMessageCount() != 0) {
4456 try server.serveErrorBundle(output.errors);4456 try server.serveErrorBundle(.error_bundle, output.errors);
4457 } else {4457 } else {
4458 try server.serveEmitDigest(&output.digest, .{4458 try server.serveEmitDigest(&output.digest, .{
4459 .flags = .{ .cache_hit = output.cache_hit },4459 .flags = .{ .cache_hit = output.cache_hit },
...@@ -4611,7 +4611,7 @@ fn serveUpdateResults(s: *Server, comp: *Compilation) !void {...@@ -4611,7 +4611,7 @@ fn serveUpdateResults(s: *Server, comp: *Compilation) !void {
4611 }4611 }
46124612
4613 if (error_bundle.errorMessageCount() > 0) {4613 if (error_bundle.errorMessageCount() > 0) {
4614 try s.serveErrorBundle(error_bundle);4614 try s.serveErrorBundle(.error_bundle, error_bundle);
4615 return;4615 return;
4616 }4616 }
46174617
...@@ -4622,7 +4622,7 @@ fn serveUpdateResults(s: *Server, comp: *Compilation) !void {...@@ -4622,7 +4622,7 @@ fn serveUpdateResults(s: *Server, comp: *Compilation) !void {
4622 }4622 }
46234623
4624 // Serve empty error bundle to indicate the update is done.4624 // Serve empty error bundle to indicate the update is done.
4625 try s.serveErrorBundle(std.zig.ErrorBundle.empty);4625 try s.serveErrorBundle(.error_bundle, std.zig.ErrorBundle.empty);
4626}4626}
46274627
4628fn runOrTest(4628fn runOrTest(
...@@ -5157,7 +5157,7 @@ fn jitCmdInner(...@@ -5157,7 +5157,7 @@ fn jitCmdInner(
5157 var error_bundle = try comp.getAllErrorsAlloc();5157 var error_bundle = try comp.getAllErrorsAlloc();
5158 defer error_bundle.deinit(comp.gpa);5158 defer error_bundle.deinit(comp.gpa);
5159 if (error_bundle.errorMessageCount() > 0) {5159 if (error_bundle.errorMessageCount() > 0) {
5160 try server.serveErrorBundle(error_bundle);5160 try server.serveErrorBundle(.error_bundle, error_bundle);
5161 process.exit(2);5161 process.exit(2);
5162 }5162 }
5163 } else {5163 } else {
tools/bsp.zig+21-37
...@@ -7,6 +7,7 @@ const Configuration = std.Build.Configuration;...@@ -7,6 +7,7 @@ const Configuration = std.Build.Configuration;
7const Client = std.zig.Client;7const Client = std.zig.Client;
8const Server = std.zig.Server;8const Server = std.zig.Server;
9const log = std.log.scoped(.bsp);9const log = std.log.scoped(.bsp);
10const panic = std.debug.panic;
1011
11pub fn main(init: std.process.Init) !void {12pub fn main(init: std.process.Init) !void {
12 const io = init.io;13 const io = init.io;
...@@ -32,7 +33,7 @@ pub fn main(init: std.process.Init) !void {...@@ -32,7 +33,7 @@ pub fn main(init: std.process.Init) !void {
32 .stdin = .pipe,33 .stdin = .pipe,
33 .stdout = .pipe,34 .stdout = .pipe,
34 .stderr = .pipe,35 .stderr = .pipe,
35 }) catch |err| std.debug.panic("failed to spawn process: {}", .{err});36 }) catch |err| panic("failed to spawn process: {}", .{err});
36 errdefer child_process.kill(io);37 errdefer child_process.kill(io);
3738
38 var multi_reader_buffer: Io.File.MultiReader.Buffer(2) = undefined;39 var multi_reader_buffer: Io.File.MultiReader.Buffer(2) = undefined;
...@@ -66,10 +67,10 @@ pub fn main(init: std.process.Init) !void {...@@ -66,10 +67,10 @@ pub fn main(init: std.process.Init) !void {
66 },67 },
67 };68 };
68 const body = client_stdout.take(header.bytes_len) catch unreachable;69 const body = client_stdout.take(header.bytes_len) catch unreachable;
69 log.debug("received {f} ({d} bytes)", .{ fmtEnum(header.tag), body.len });70 log.debug("received {} ({d} bytes)", .{ header.tag, body.len });
7071
71 if (header.tag != .bsp_handshake) {72 if (header.tag != .bsp_handshake) {
72 log.err("received unexpected message: {f}", .{fmtEnum(header.tag)});73 log.err("received unexpected message: {}", .{header.tag});
73 return error.UnexpectedMessage;74 return error.UnexpectedMessage;
74 }75 }
7576
...@@ -94,17 +95,26 @@ pub fn main(init: std.process.Init) !void {...@@ -94,17 +95,26 @@ pub fn main(init: std.process.Init) !void {
94 const body = client_stdout.take(header.bytes_len) catch unreachable;95 const body = client_stdout.take(header.bytes_len) catch unreachable;
95 log.debug("received {t} ({d} bytes)", .{ header.tag, body.len });96 log.debug("received {t} ({d} bytes)", .{ header.tag, body.len });
9697
97 if (header.tag != .bsp_configuration) {98 switch (header.tag) {
98 log.err("received unexpected message: {f}", .{fmtEnum(header.tag)});99 .bsp_configuration => {},
99 return error.UnexpectedMessage;100 .bsp_configuration_failed => {
101 var eb = try Server.allocErrorBundle(gpa, body);
102 defer eb.deinit(gpa);
103 try eb.renderToStderr(io, .{}, .auto);
104 panic("configuration failed", .{});
105 },
106 else => {
107 log.err("received unexpected message: {}", .{header.tag});
108 return error.UnexpectedMessage;
109 },
100 }110 }
101111
102 const configuration_path = body;112 const configuration_path = body;
103 var file = Io.Dir.cwd().openFile(io, configuration_path, .{}) catch |err|113 var file = Io.Dir.cwd().openFile(io, configuration_path, .{}) catch |err|
104 std.debug.panic("failed to open configuration file {q}: {t}", .{ configuration_path, err });114 panic("failed to open configuration file {q}: {t}", .{ configuration_path, err });
105 defer file.close(io);115 defer file.close(io);
106 break :configuration Configuration.loadFile(conf_arena, io, file) catch |err|116 break :configuration Configuration.loadFile(conf_arena, io, file) catch |err|
107 std.debug.panic("failed to load configuration file {q}: {t}", .{ configuration_path, err });117 panic("failed to load configuration file {q}: {t}", .{ configuration_path, err });
108 };118 };
109 const c = &configuration;119 const c = &configuration;
110120
...@@ -157,7 +167,7 @@ pub fn main(init: std.process.Init) !void {...@@ -157,7 +167,7 @@ pub fn main(init: std.process.Init) !void {
157 if (std.fmt.parseInt(u32, arg, 10)) |i|167 if (std.fmt.parseInt(u32, arg, 10)) |i|
158 @fromBackingInt(i)168 @fromBackingInt(i)
159 else |_|169 else |_|
160 top_level_steps.get(arg) orelse std.debug.panic("unexpected step name or index", .{});170 top_level_steps.get(arg) orelse panic("unexpected step name or index", .{});
161 try steps.append(gpa, step);171 try steps.append(gpa, step);
162 }172 }
163 }173 }
...@@ -178,7 +188,7 @@ pub fn main(init: std.process.Init) !void {...@@ -178,7 +188,7 @@ pub fn main(init: std.process.Init) !void {
178 },188 },
179 };189 };
180 const body = client_stdout.take(header.bytes_len) catch unreachable;190 const body = client_stdout.take(header.bytes_len) catch unreachable;
181 log.debug("received {f} ({d} bytes)", .{ fmtEnum(header.tag), body.len });191 log.debug("received {} ({d} bytes)", .{ header.tag, body.len });
182192
183 switch (header.tag) {193 switch (header.tag) {
184 .bsp_build_started => {},194 .bsp_build_started => {},
...@@ -214,7 +224,7 @@ pub fn main(init: std.process.Init) !void {...@@ -214,7 +224,7 @@ pub fn main(init: std.process.Init) !void {
214 }224 }
215 },225 },
216 .bsp_configuration => @panic("TODO"),226 .bsp_configuration => @panic("TODO"),
217 else => std.debug.panic("received unexpected message: {f}", .{fmtEnum(header.tag)}),227 else => panic("received unexpected message: {}", .{header.tag}),
218 }228 }
219 }229 }
220 continue;230 continue;
...@@ -242,29 +252,3 @@ pub fn main(init: std.process.Init) !void {...@@ -242,29 +252,3 @@ pub fn main(init: std.process.Init) !void {
242 log.err("maker {f}", .{term});252 log.err("maker {f}", .{term});
243 }253 }
244}254}
245
246const FormatEnum = union(enum) {
247 named: []const u8,
248 unnamed: usize,
249
250 pub fn format(
251 e: FormatEnum,
252 writer: *std.Io.Writer,
253 ) std.Io.Writer.Error!void {
254 switch (e) {
255 .named => |name| {
256 try writer.writeByte('.');
257 try writer.writeAll(name);
258 },
259 .unnamed => |number| try writer.print("0x{x}", .{number}),
260 }
261 }
262};
263
264fn fmtEnum(e: anytype) FormatEnum {
265 if (std.enums.tagName(@TypeOf(e), e)) |name| {
266 return .{ .named = name };
267 } else {
268 return .{ .unnamed = @backingInt(e) };
269 }
270}