authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-10-28 12:42:05+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-10-30 09:31:28+00:00
log74931fe25cdd94e1cd08b5ece9dcce19959bc079
tree75449b1d594d55a872aeb03f2dd3be16ac396274
parent74c23a237ef5245b63eb06b832a511aabeb715c0
signaturelock-open Commit is signed but in an unrecognized format.

std.debug.lockStderrWriter: also return ttyconf

`std.Io.tty.Config.detect` may be an expensive check (e.g. involving syscalls), and doing it every time we need to print isn't really necessary; under normal usage, we can compute the value once and cache it for the whole program's execution. Since anyone outputting to stderr may reasonably want this information (in fact they are very likely to), it makes sense to cache it and return it from `lockStderrWriter`. Call sites who do not need it will experience no significant overhead, and can just ignore the TTY config with a `const w, _` destructure.

37 files changed, 169 insertions(+), 193 deletions(-)

lib/compiler/build_runner.zig+16-25
...@@ -442,8 +442,7 @@ pub fn main() !void {...@@ -442,8 +442,7 @@ pub fn main() !void {
442 if (builtin.single_threaded) fatal("'--webui' is not yet supported on single-threaded hosts", .{});442 if (builtin.single_threaded) fatal("'--webui' is not yet supported on single-threaded hosts", .{});
443 }443 }
444444
445 const stderr: std.fs.File = .stderr();445 const ttyconf = color.detectTtyConf();
446 const ttyconf = get_tty_conf(color, stderr);
447 switch (ttyconf) {446 switch (ttyconf) {
448 .no_color => try graph.env_map.put("NO_COLOR", "1"),447 .no_color => try graph.env_map.put("NO_COLOR", "1"),
449 .escape_codes => try graph.env_map.put("CLICOLOR_FORCE", "1"),448 .escape_codes => try graph.env_map.put("CLICOLOR_FORCE", "1"),
...@@ -522,9 +521,9 @@ pub fn main() !void {...@@ -522,9 +521,9 @@ pub fn main() !void {
522 .error_style = error_style,521 .error_style = error_style,
523 .multiline_errors = multiline_errors,522 .multiline_errors = multiline_errors,
524 .summary = summary orelse if (watch or webui_listen != null) .line else .failures,523 .summary = summary orelse if (watch or webui_listen != null) .line else .failures,
525 .ttyconf = ttyconf,
526 .stderr = stderr,
527 .thread_pool = undefined,524 .thread_pool = undefined,
525
526 .ttyconf = ttyconf,
528 };527 };
529 defer {528 defer {
530 run.memory_blocked_steps.deinit(gpa);529 run.memory_blocked_steps.deinit(gpa);
...@@ -563,9 +562,9 @@ pub fn main() !void {...@@ -563,9 +562,9 @@ pub fn main() !void {
563 break :ws .init(.{562 break :ws .init(.{
564 .gpa = gpa,563 .gpa = gpa,
565 .thread_pool = &run.thread_pool,564 .thread_pool = &run.thread_pool,
565 .ttyconf = ttyconf,
566 .graph = &graph,566 .graph = &graph,
567 .all_steps = run.step_stack.keys(),567 .all_steps = run.step_stack.keys(),
568 .ttyconf = run.ttyconf,
569 .root_prog_node = main_progress_node,568 .root_prog_node = main_progress_node,
570 .watch = watch,569 .watch = watch,
571 .listen_address = listen_address,570 .listen_address = listen_address,
...@@ -578,7 +577,7 @@ pub fn main() !void {...@@ -578,7 +577,7 @@ pub fn main() !void {
578 }577 }
579578
580 rebuild: while (true) : (if (run.error_style.clearOnUpdate()) {579 rebuild: while (true) : (if (run.error_style.clearOnUpdate()) {
581 const bw = std.debug.lockStderrWriter(&stdio_buffer_allocation);580 const bw, _ = std.debug.lockStderrWriter(&stdio_buffer_allocation);
582 defer std.debug.unlockStderrWriter();581 defer std.debug.unlockStderrWriter();
583 try bw.writeAll("\x1B[2J\x1B[3J\x1B[H");582 try bw.writeAll("\x1B[2J\x1B[3J\x1B[H");
584 }) {583 }) {
...@@ -682,13 +681,14 @@ const Run = struct {...@@ -682,13 +681,14 @@ const Run = struct {
682 /// Allocated into `gpa`.681 /// Allocated into `gpa`.
683 step_stack: std.AutoArrayHashMapUnmanaged(*Step, void),682 step_stack: std.AutoArrayHashMapUnmanaged(*Step, void),
684 thread_pool: std.Thread.Pool,683 thread_pool: std.Thread.Pool,
684 /// Similar to the `tty.Config` returned by `std.debug.lockStderrWriter`,
685 /// but also respects the '--color' flag.
686 ttyconf: tty.Config,
685687
686 claimed_rss: usize,688 claimed_rss: usize,
687 error_style: ErrorStyle,689 error_style: ErrorStyle,
688 multiline_errors: MultilineErrors,690 multiline_errors: MultilineErrors,
689 summary: Summary,691 summary: Summary,
690 ttyconf: tty.Config,
691 stderr: File,
692};692};
693693
694fn prepare(694fn prepare(
...@@ -834,8 +834,6 @@ fn runStepNames(...@@ -834,8 +834,6 @@ fn runStepNames(
834 }834 }
835 }835 }
836836
837 const ttyconf = run.ttyconf;
838
839 if (fuzz) |mode| blk: {837 if (fuzz) |mode| blk: {
840 switch (builtin.os.tag) {838 switch (builtin.os.tag) {
841 // Current implementation depends on two things that need to be ported to Windows:839 // Current implementation depends on two things that need to be ported to Windows:
...@@ -863,9 +861,9 @@ fn runStepNames(...@@ -863,9 +861,9 @@ fn runStepNames(
863 gpa,861 gpa,
864 io,862 io,
865 thread_pool,863 thread_pool,
864 run.ttyconf,
866 step_stack.keys(),865 step_stack.keys(),
867 parent_prog_node,866 parent_prog_node,
868 ttyconf,
869 mode,867 mode,
870 ) catch |err| fatal("failed to start fuzzer: {s}", .{@errorName(err)});868 ) catch |err| fatal("failed to start fuzzer: {s}", .{@errorName(err)});
871 defer f.deinit();869 defer f.deinit();
...@@ -890,8 +888,9 @@ fn runStepNames(...@@ -890,8 +888,9 @@ fn runStepNames(
890 .none => break :summary,888 .none => break :summary,
891 }889 }
892890
893 const w = std.debug.lockStderrWriter(&stdio_buffer_allocation);891 const w, _ = std.debug.lockStderrWriter(&stdio_buffer_allocation);
894 defer std.debug.unlockStderrWriter();892 defer std.debug.unlockStderrWriter();
893 const ttyconf = run.ttyconf;
895894
896 const total_count = success_count + failure_count + pending_count + skipped_count;895 const total_count = success_count + failure_count + pending_count + skipped_count;
897 ttyconf.setColor(w, .cyan) catch {};896 ttyconf.setColor(w, .cyan) catch {};
...@@ -1399,9 +1398,10 @@ fn workerMakeOneStep(...@@ -1399,9 +1398,10 @@ fn workerMakeOneStep(
1399 const show_error_msgs = s.result_error_msgs.items.len > 0;1398 const show_error_msgs = s.result_error_msgs.items.len > 0;
1400 const show_stderr = s.result_stderr.len > 0;1399 const show_stderr = s.result_stderr.len > 0;
1401 if (show_error_msgs or show_compile_errors or show_stderr) {1400 if (show_error_msgs or show_compile_errors or show_stderr) {
1402 const bw = std.debug.lockStderrWriter(&stdio_buffer_allocation);1401 const bw, _ = std.debug.lockStderrWriter(&stdio_buffer_allocation);
1403 defer std.debug.unlockStderrWriter();1402 defer std.debug.unlockStderrWriter();
1404 printErrorMessages(run.gpa, s, .{ .ttyconf = run.ttyconf }, bw, run.error_style, run.multiline_errors) catch {};1403 const ttyconf = run.ttyconf;
1404 printErrorMessages(run.gpa, s, .{}, bw, ttyconf, run.error_style, run.multiline_errors) catch {};
1405 }1405 }
14061406
1407 handle_result: {1407 handle_result: {
...@@ -1465,11 +1465,10 @@ pub fn printErrorMessages(...@@ -1465,11 +1465,10 @@ pub fn printErrorMessages(
1465 failing_step: *Step,1465 failing_step: *Step,
1466 options: std.zig.ErrorBundle.RenderOptions,1466 options: std.zig.ErrorBundle.RenderOptions,
1467 stderr: *Writer,1467 stderr: *Writer,
1468 ttyconf: tty.Config,
1468 error_style: ErrorStyle,1469 error_style: ErrorStyle,
1469 multiline_errors: MultilineErrors,1470 multiline_errors: MultilineErrors,
1470) !void {1471) !void {
1471 const ttyconf = options.ttyconf;
1472
1473 if (error_style.verboseContext()) {1472 if (error_style.verboseContext()) {
1474 // Provide context for where these error messages are coming from by1473 // Provide context for where these error messages are coming from by
1475 // printing the corresponding Step subtree.1474 // printing the corresponding Step subtree.
...@@ -1513,7 +1512,7 @@ pub fn printErrorMessages(...@@ -1513,7 +1512,7 @@ pub fn printErrorMessages(
1513 }1512 }
1514 }1513 }
15151514
1516 try failing_step.result_error_bundle.renderToWriter(options, stderr);1515 try failing_step.result_error_bundle.renderToWriter(options, stderr, ttyconf);
15171516
1518 for (failing_step.result_error_msgs.items) |msg| {1517 for (failing_step.result_error_msgs.items) |msg| {
1519 try ttyconf.setColor(stderr, .red);1518 try ttyconf.setColor(stderr, .red);
...@@ -1759,14 +1758,6 @@ const ErrorStyle = enum {...@@ -1759,14 +1758,6 @@ const ErrorStyle = enum {
1759const MultilineErrors = enum { indent, newline, none };1758const MultilineErrors = enum { indent, newline, none };
1760const Summary = enum { all, new, failures, line, none };1759const Summary = enum { all, new, failures, line, none };
17611760
1762fn get_tty_conf(color: Color, stderr: File) tty.Config {
1763 return switch (color) {
1764 .auto => tty.detectConfig(stderr),
1765 .on => .escape_codes,
1766 .off => .no_color,
1767 };
1768}
1769
1770fn fatalWithHint(comptime f: []const u8, args: anytype) noreturn {1761fn fatalWithHint(comptime f: []const u8, args: anytype) noreturn {
1771 std.debug.print(f ++ "\n access the help menu with 'zig build -h'\n", args);1762 std.debug.print(f ++ "\n access the help menu with 'zig build -h'\n", args);
1772 process.exit(1);1763 process.exit(1);
lib/compiler/resinator/cli.zig+3-3
...@@ -124,10 +124,10 @@ pub const Diagnostics = struct {...@@ -124,10 +124,10 @@ pub const Diagnostics = struct {
124 try self.errors.append(self.allocator, error_details);124 try self.errors.append(self.allocator, error_details);
125 }125 }
126126
127 pub fn renderToStdErr(self: *Diagnostics, args: []const []const u8, config: std.Io.tty.Config) void {127 pub fn renderToStdErr(self: *Diagnostics, args: []const []const u8) void {
128 const stderr = std.debug.lockStderrWriter(&.{});128 const stderr, const ttyconf = std.debug.lockStderrWriter(&.{});
129 defer std.debug.unlockStderrWriter();129 defer std.debug.unlockStderrWriter();
130 self.renderToWriter(args, stderr, config) catch return;130 self.renderToWriter(args, stderr, ttyconf) catch return;
131 }131 }
132132
133 pub fn renderToWriter(self: *Diagnostics, args: []const []const u8, writer: *std.Io.Writer, config: std.Io.tty.Config) !void {133 pub fn renderToWriter(self: *Diagnostics, args: []const []const u8, writer: *std.Io.Writer, config: std.Io.tty.Config) !void {
lib/compiler/resinator/errors.zig+3-8
...@@ -67,20 +67,15 @@ pub const Diagnostics = struct {...@@ -67,20 +67,15 @@ pub const Diagnostics = struct {
67 return @intCast(index);67 return @intCast(index);
68 }68 }
6969
70 pub fn renderToStdErr(self: *Diagnostics, cwd: std.fs.Dir, source: []const u8, tty_config: std.Io.tty.Config, source_mappings: ?SourceMappings) void {70 pub fn renderToStdErr(self: *Diagnostics, cwd: std.fs.Dir, source: []const u8, source_mappings: ?SourceMappings) void {
71 const io = self.io;71 const io = self.io;
72 const stderr = std.debug.lockStderrWriter(&.{});72 const stderr, const ttyconf = std.debug.lockStderrWriter(&.{});
73 defer std.debug.unlockStderrWriter();73 defer std.debug.unlockStderrWriter();
74 for (self.errors.items) |err_details| {74 for (self.errors.items) |err_details| {
75 renderErrorMessage(io, stderr, tty_config, cwd, err_details, source, self.strings.items, source_mappings) catch return;75 renderErrorMessage(io, stderr, ttyconf, cwd, err_details, source, self.strings.items, source_mappings) catch return;
76 }76 }
77 }77 }
7878
79 pub fn renderToStdErrDetectTTY(self: *Diagnostics, cwd: std.fs.Dir, source: []const u8, source_mappings: ?SourceMappings) void {
80 const tty_config = std.Io.tty.detectConfig(std.fs.File.stderr());
81 return self.renderToStdErr(cwd, source, tty_config, source_mappings);
82 }
83
84 pub fn contains(self: *const Diagnostics, err: ErrorDetails.Error) bool {79 pub fn contains(self: *const Diagnostics, err: ErrorDetails.Error) bool {
85 for (self.errors.items) |details| {80 for (self.errors.items) |details| {
86 if (details.err == err) return true;81 if (details.err == err) return true;
lib/compiler/resinator/main.zig+29-34
...@@ -28,13 +28,11 @@ pub fn main() !void {...@@ -28,13 +28,11 @@ pub fn main() !void {
28 defer arena_state.deinit();28 defer arena_state.deinit();
29 const arena = arena_state.allocator();29 const arena = arena_state.allocator();
3030
31 const stderr = std.fs.File.stderr();
32 const stderr_config = std.Io.tty.detectConfig(stderr);
33
34 const args = try std.process.argsAlloc(arena);31 const args = try std.process.argsAlloc(arena);
3532
36 if (args.len < 2) {33 if (args.len < 2) {
37 try renderErrorMessage(std.debug.lockStderrWriter(&.{}), stderr_config, .err, "expected zig lib dir as first argument", .{});34 const w, const ttyconf = std.debug.lockStderrWriter(&.{});
35 try renderErrorMessage(w, ttyconf, .err, "expected zig lib dir as first argument", .{});
38 std.process.exit(1);36 std.process.exit(1);
39 }37 }
40 const zig_lib_dir = args[1];38 const zig_lib_dir = args[1];
...@@ -56,9 +54,7 @@ pub fn main() !void {...@@ -56,9 +54,7 @@ pub fn main() !void {
56 .in = undefined, // won't be receiving messages54 .in = undefined, // won't be receiving messages
57 },55 },
58 },56 },
59 false => .{57 false => .stderr,
60 .tty = stderr_config,
61 },
62 };58 };
6359
64 var options = options: {60 var options = options: {
...@@ -75,12 +71,14 @@ pub fn main() !void {...@@ -75,12 +71,14 @@ pub fn main() !void {
7571
76 if (!zig_integration) {72 if (!zig_integration) {
77 // print any warnings/notes73 // print any warnings/notes
78 cli_diagnostics.renderToStdErr(cli_args, stderr_config);74 cli_diagnostics.renderToStdErr(cli_args);
79 // If there was something printed, then add an extra newline separator75 // If there was something printed, then add an extra newline separator
80 // so that there is a clear separation between the cli diagnostics and whatever76 // so that there is a clear separation between the cli diagnostics and whatever
81 // gets printed after77 // gets printed after
82 if (cli_diagnostics.errors.items.len > 0) {78 if (cli_diagnostics.errors.items.len > 0) {
83 try stderr.writeAll("\n");79 const stderr, _ = std.debug.lockStderrWriter(&.{});
80 defer std.debug.unlockStderrWriter();
81 try stderr.writeByte('\n');
84 }82 }
85 }83 }
86 break :options options;84 break :options options;
...@@ -130,17 +128,18 @@ pub fn main() !void {...@@ -130,17 +128,18 @@ pub fn main() !void {
130 const aro_arena = aro_arena_state.allocator();128 const aro_arena = aro_arena_state.allocator();
131129
132 var stderr_buf: [512]u8 = undefined;130 var stderr_buf: [512]u8 = undefined;
133 var stderr_writer = stderr.writer(&stderr_buf);131 var diagnostics: aro.Diagnostics = .{ .output = output: {
134 var diagnostics: aro.Diagnostics = switch (zig_integration) {132 if (zig_integration) break :output .{ .to_list = .{ .arena = .init(gpa) } };
135 false => .{ .output = .{ .to_writer = .{133 const w, const ttyconf = std.debug.lockStderrWriter(&stderr_buf);
136 .writer = &stderr_writer.interface,134 break :output .{ .to_writer = .{
137 .color = stderr_config,135 .writer = w,
138 } } },136 .color = ttyconf,
139 true => .{ .output = .{ .to_list = .{137 } };
140 .arena = .init(gpa),138 } };
141 } } },139 defer {
142 };140 diagnostics.deinit();
143 defer diagnostics.deinit();141 if (!zig_integration) std.debug.unlockStderrWriter();
142 }
144143
145 var comp = aro.Compilation.init(aro_arena, aro_arena, io, &diagnostics, std.fs.cwd());144 var comp = aro.Compilation.init(aro_arena, aro_arena, io, &diagnostics, std.fs.cwd());
146 defer comp.deinit();145 defer comp.deinit();
...@@ -307,7 +306,7 @@ pub fn main() !void {...@@ -307,7 +306,7 @@ pub fn main() !void {
307306
308 // print any warnings/notes307 // print any warnings/notes
309 if (!zig_integration) {308 if (!zig_integration) {
310 diagnostics.renderToStdErr(std.fs.cwd(), final_input, stderr_config, mapping_results.mappings);309 diagnostics.renderToStdErr(std.fs.cwd(), final_input, mapping_results.mappings);
311 }310 }
312311
313 // write the depfile312 // write the depfile
...@@ -660,7 +659,7 @@ const SourceMappings = @import("source_mapping.zig").SourceMappings;...@@ -660,7 +659,7 @@ const SourceMappings = @import("source_mapping.zig").SourceMappings;
660659
661const ErrorHandler = union(enum) {660const ErrorHandler = union(enum) {
662 server: std.zig.Server,661 server: std.zig.Server,
663 tty: std.Io.tty.Config,662 stderr,
664663
665 pub fn emitCliDiagnostics(664 pub fn emitCliDiagnostics(
666 self: *ErrorHandler,665 self: *ErrorHandler,
...@@ -675,9 +674,7 @@ const ErrorHandler = union(enum) {...@@ -675,9 +674,7 @@ const ErrorHandler = union(enum) {
675674
676 try server.serveErrorBundle(error_bundle);675 try server.serveErrorBundle(error_bundle);
677 },676 },
678 .tty => {677 .stderr => diagnostics.renderToStdErr(args),
679 diagnostics.renderToStdErr(args, self.tty);
680 },
681 }678 }
682 }679 }
683680
...@@ -698,11 +695,11 @@ const ErrorHandler = union(enum) {...@@ -698,11 +695,11 @@ const ErrorHandler = union(enum) {
698695
699 try server.serveErrorBundle(error_bundle);696 try server.serveErrorBundle(error_bundle);
700 },697 },
701 .tty => {698 .stderr => {
702 // aro errors have already been emitted699 // aro errors have already been emitted
703 const stderr = std.debug.lockStderrWriter(&.{});700 const stderr, const ttyconf = std.debug.lockStderrWriter(&.{});
704 defer std.debug.unlockStderrWriter();701 defer std.debug.unlockStderrWriter();
705 try renderErrorMessage(stderr, self.tty, .err, "{s}", .{fail_msg});702 try renderErrorMessage(stderr, ttyconf, .err, "{s}", .{fail_msg});
706 },703 },
707 }704 }
708 }705 }
...@@ -722,9 +719,7 @@ const ErrorHandler = union(enum) {...@@ -722,9 +719,7 @@ const ErrorHandler = union(enum) {
722719
723 try server.serveErrorBundle(error_bundle);720 try server.serveErrorBundle(error_bundle);
724 },721 },
725 .tty => {722 .stderr => diagnostics.renderToStdErr(cwd, source, mappings),
726 diagnostics.renderToStdErr(cwd, source, self.tty, mappings);
727 },
728 }723 }
729 }724 }
730725
...@@ -745,10 +740,10 @@ const ErrorHandler = union(enum) {...@@ -745,10 +740,10 @@ const ErrorHandler = union(enum) {
745740
746 try server.serveErrorBundle(error_bundle);741 try server.serveErrorBundle(error_bundle);
747 },742 },
748 .tty => {743 .stderr => {
749 const stderr = std.debug.lockStderrWriter(&.{});744 const stderr, const ttyconf = std.debug.lockStderrWriter(&.{});
750 defer std.debug.unlockStderrWriter();745 defer std.debug.unlockStderrWriter();
751 try renderErrorMessage(stderr, self.tty, msg_type, format, args);746 try renderErrorMessage(stderr, ttyconf, msg_type, format, args);
752 },747 },
753 }748 }
754 }749 }
lib/compiler/std-docs.zig+1-2
...@@ -394,8 +394,7 @@ fn buildWasmBinary(...@@ -394,8 +394,7 @@ fn buildWasmBinary(
394 }394 }
395395
396 if (result_error_bundle.errorMessageCount() > 0) {396 if (result_error_bundle.errorMessageCount() > 0) {
397 const color = std.zig.Color.auto;397 result_error_bundle.renderToStdErr(.{}, true);
398 result_error_bundle.renderToStdErr(color.renderOptions());
399 std.log.err("the following command failed with {d} compilation errors:\n{s}", .{398 std.log.err("the following command failed with {d} compilation errors:\n{s}", .{
400 result_error_bundle.errorMessageCount(),399 result_error_bundle.errorMessageCount(),
401 try std.Build.Step.allocPrintCmd(arena, null, argv.items),400 try std.Build.Step.allocPrintCmd(arena, null, argv.items),
lib/std/Build.zig+5-7
...@@ -2257,8 +2257,8 @@ pub const GeneratedFile = struct {...@@ -2257,8 +2257,8 @@ pub const GeneratedFile = struct {
22572257
2258 pub fn getPath2(gen: GeneratedFile, src_builder: *Build, asking_step: ?*Step) []const u8 {2258 pub fn getPath2(gen: GeneratedFile, src_builder: *Build, asking_step: ?*Step) []const u8 {
2259 return gen.path orelse {2259 return gen.path orelse {
2260 const w = debug.lockStderrWriter(&.{});2260 const w, const ttyconf = debug.lockStderrWriter(&.{});
2261 dumpBadGetPathHelp(gen.step, w, .detect(.stderr()), src_builder, asking_step) catch {};2261 dumpBadGetPathHelp(gen.step, w, ttyconf, src_builder, asking_step) catch {};
2262 debug.unlockStderrWriter();2262 debug.unlockStderrWriter();
2263 @panic("misconfigured build script");2263 @panic("misconfigured build script");
2264 };2264 };
...@@ -2466,8 +2466,8 @@ pub const LazyPath = union(enum) {...@@ -2466,8 +2466,8 @@ pub const LazyPath = union(enum) {
2466 var file_path: Cache.Path = .{2466 var file_path: Cache.Path = .{
2467 .root_dir = Cache.Directory.cwd(),2467 .root_dir = Cache.Directory.cwd(),
2468 .sub_path = gen.file.path orelse {2468 .sub_path = gen.file.path orelse {
2469 const w = debug.lockStderrWriter(&.{});2469 const w, const ttyconf = debug.lockStderrWriter(&.{});
2470 dumpBadGetPathHelp(gen.file.step, w, .detect(.stderr()), src_builder, asking_step) catch {};2470 dumpBadGetPathHelp(gen.file.step, w, ttyconf, src_builder, asking_step) catch {};
2471 debug.unlockStderrWriter();2471 debug.unlockStderrWriter();
2472 @panic("misconfigured build script");2472 @panic("misconfigured build script");
2473 },2473 },
...@@ -2558,13 +2558,11 @@ fn dumpBadDirnameHelp(...@@ -2558,13 +2558,11 @@ fn dumpBadDirnameHelp(
2558 comptime msg: []const u8,2558 comptime msg: []const u8,
2559 args: anytype,2559 args: anytype,
2560) anyerror!void {2560) anyerror!void {
2561 const w = debug.lockStderrWriter(&.{});2561 const w, const tty_config = debug.lockStderrWriter(&.{});
2562 defer debug.unlockStderrWriter();2562 defer debug.unlockStderrWriter();
25632563
2564 try w.print(msg, args);2564 try w.print(msg, args);
25652565
2566 const tty_config = std.Io.tty.detectConfig(.stderr());
2567
2568 if (fail_step) |s| {2566 if (fail_step) |s| {
2569 tty_config.setColor(w, .red) catch {};2567 tty_config.setColor(w, .red) catch {};
2570 try w.writeAll(" The step was created by this stack trace:\n");2568 try w.writeAll(" The step was created by this stack trace:\n");
lib/std/Build/Fuzz.zig+9-9
...@@ -16,6 +16,7 @@ const build_runner = @import("root");...@@ -16,6 +16,7 @@ const build_runner = @import("root");
1616
17gpa: Allocator,17gpa: Allocator,
18io: Io,18io: Io,
19ttyconf: tty.Config,
19mode: Mode,20mode: Mode,
2021
21/// Allocated into `gpa`.22/// Allocated into `gpa`.
...@@ -25,7 +26,6 @@ wait_group: std.Thread.WaitGroup,...@@ -25,7 +26,6 @@ wait_group: std.Thread.WaitGroup,
25root_prog_node: std.Progress.Node,26root_prog_node: std.Progress.Node,
26prog_node: std.Progress.Node,27prog_node: std.Progress.Node,
27thread_pool: *std.Thread.Pool,28thread_pool: *std.Thread.Pool,
28ttyconf: tty.Config,
2929
30/// Protects `coverage_files`.30/// Protects `coverage_files`.
31coverage_mutex: std.Thread.Mutex,31coverage_mutex: std.Thread.Mutex,
...@@ -79,9 +79,9 @@ pub fn init(...@@ -79,9 +79,9 @@ pub fn init(
79 gpa: Allocator,79 gpa: Allocator,
80 io: Io,80 io: Io,
81 thread_pool: *std.Thread.Pool,81 thread_pool: *std.Thread.Pool,
82 ttyconf: tty.Config,
82 all_steps: []const *Build.Step,83 all_steps: []const *Build.Step,
83 root_prog_node: std.Progress.Node,84 root_prog_node: std.Progress.Node,
84 ttyconf: tty.Config,
85 mode: Mode,85 mode: Mode,
86) Allocator.Error!Fuzz {86) Allocator.Error!Fuzz {
87 const run_steps: []const *Step.Run = steps: {87 const run_steps: []const *Step.Run = steps: {
...@@ -115,11 +115,11 @@ pub fn init(...@@ -115,11 +115,11 @@ pub fn init(
115 return .{115 return .{
116 .gpa = gpa,116 .gpa = gpa,
117 .io = io,117 .io = io,
118 .ttyconf = ttyconf,
118 .mode = mode,119 .mode = mode,
119 .run_steps = run_steps,120 .run_steps = run_steps,
120 .wait_group = .{},121 .wait_group = .{},
121 .thread_pool = thread_pool,122 .thread_pool = thread_pool,
122 .ttyconf = ttyconf,
123 .root_prog_node = root_prog_node,123 .root_prog_node = root_prog_node,
124 .prog_node = .none,124 .prog_node = .none,
125 .coverage_files = .empty,125 .coverage_files = .empty,
...@@ -158,7 +158,7 @@ pub fn deinit(fuzz: *Fuzz) void {...@@ -158,7 +158,7 @@ pub fn deinit(fuzz: *Fuzz) void {
158 fuzz.gpa.free(fuzz.run_steps);158 fuzz.gpa.free(fuzz.run_steps);
159}159}
160160
161fn rebuildTestsWorkerRun(run: *Step.Run, gpa: Allocator, ttyconf: std.Io.tty.Config, parent_prog_node: std.Progress.Node) void {161fn rebuildTestsWorkerRun(run: *Step.Run, gpa: Allocator, ttyconf: tty.Config, parent_prog_node: std.Progress.Node) void {
162 rebuildTestsWorkerRunFallible(run, gpa, ttyconf, parent_prog_node) catch |err| {162 rebuildTestsWorkerRunFallible(run, gpa, ttyconf, parent_prog_node) catch |err| {
163 const compile = run.producer.?;163 const compile = run.producer.?;
164 log.err("step '{s}': failed to rebuild in fuzz mode: {s}", .{164 log.err("step '{s}': failed to rebuild in fuzz mode: {s}", .{
...@@ -167,7 +167,7 @@ fn rebuildTestsWorkerRun(run: *Step.Run, gpa: Allocator, ttyconf: std.Io.tty.Con...@@ -167,7 +167,7 @@ fn rebuildTestsWorkerRun(run: *Step.Run, gpa: Allocator, ttyconf: std.Io.tty.Con
167 };167 };
168}168}
169169
170fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, ttyconf: std.Io.tty.Config, parent_prog_node: std.Progress.Node) !void {170fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, ttyconf: tty.Config, parent_prog_node: std.Progress.Node) !void {
171 const compile = run.producer.?;171 const compile = run.producer.?;
172 const prog_node = parent_prog_node.start(compile.step.name, 0);172 const prog_node = parent_prog_node.start(compile.step.name, 0);
173 defer prog_node.end();173 defer prog_node.end();
...@@ -180,9 +180,9 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, ttyconf: std.Io...@@ -180,9 +180,9 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, ttyconf: std.Io
180180
181 if (show_error_msgs or show_compile_errors or show_stderr) {181 if (show_error_msgs or show_compile_errors or show_stderr) {
182 var buf: [256]u8 = undefined;182 var buf: [256]u8 = undefined;
183 const w = std.debug.lockStderrWriter(&buf);183 const w, _ = std.debug.lockStderrWriter(&buf);
184 defer std.debug.unlockStderrWriter();184 defer std.debug.unlockStderrWriter();
185 build_runner.printErrorMessages(gpa, &compile.step, .{ .ttyconf = ttyconf }, w, .verbose, .indent) catch {};185 build_runner.printErrorMessages(gpa, &compile.step, .{}, w, ttyconf, .verbose, .indent) catch {};
186 }186 }
187187
188 const rebuilt_bin_path = result catch |err| switch (err) {188 const rebuilt_bin_path = result catch |err| switch (err) {
...@@ -206,9 +206,9 @@ fn fuzzWorkerRun(...@@ -206,9 +206,9 @@ fn fuzzWorkerRun(
206 run.rerunInFuzzMode(fuzz, unit_test_index, prog_node) catch |err| switch (err) {206 run.rerunInFuzzMode(fuzz, unit_test_index, prog_node) catch |err| switch (err) {
207 error.MakeFailed => {207 error.MakeFailed => {
208 var buf: [256]u8 = undefined;208 var buf: [256]u8 = undefined;
209 const w = std.debug.lockStderrWriter(&buf);209 const w, _ = std.debug.lockStderrWriter(&buf);
210 defer std.debug.unlockStderrWriter();210 defer std.debug.unlockStderrWriter();
211 build_runner.printErrorMessages(gpa, &run.step, .{ .ttyconf = fuzz.ttyconf }, w, .verbose, .indent) catch {};211 build_runner.printErrorMessages(gpa, &run.step, .{}, w, fuzz.ttyconf, .verbose, .indent) catch {};
212 return;212 return;
213 },213 },
214 else => {214 else => {
lib/std/Build/Step/Compile.zig+5-6
...@@ -1056,15 +1056,15 @@ fn getGeneratedFilePath(compile: *Compile, comptime tag_name: []const u8, asking...@@ -1056,15 +1056,15 @@ fn getGeneratedFilePath(compile: *Compile, comptime tag_name: []const u8, asking
1056 const maybe_path: ?*GeneratedFile = @field(compile, tag_name);1056 const maybe_path: ?*GeneratedFile = @field(compile, tag_name);
10571057
1058 const generated_file = maybe_path orelse {1058 const generated_file = maybe_path orelse {
1059 const w = std.debug.lockStderrWriter(&.{});1059 const w, const ttyconf = std.debug.lockStderrWriter(&.{});
1060 std.Build.dumpBadGetPathHelp(&compile.step, w, .detect(.stderr()), compile.step.owner, asking_step) catch {};1060 std.Build.dumpBadGetPathHelp(&compile.step, w, ttyconf, compile.step.owner, asking_step) catch {};
1061 std.debug.unlockStderrWriter();1061 std.debug.unlockStderrWriter();
1062 @panic("missing emit option for " ++ tag_name);1062 @panic("missing emit option for " ++ tag_name);
1063 };1063 };
10641064
1065 const path = generated_file.path orelse {1065 const path = generated_file.path orelse {
1066 const w = std.debug.lockStderrWriter(&.{});1066 const w, const ttyconf = std.debug.lockStderrWriter(&.{});
1067 std.Build.dumpBadGetPathHelp(&compile.step, w, .detect(.stderr()), compile.step.owner, asking_step) catch {};1067 std.Build.dumpBadGetPathHelp(&compile.step, w, ttyconf, compile.step.owner, asking_step) catch {};
1068 std.debug.unlockStderrWriter();1068 std.debug.unlockStderrWriter();
1069 @panic(tag_name ++ " is null. Is there a missing step dependency?");1069 @panic(tag_name ++ " is null. Is there a missing step dependency?");
1070 };1070 };
...@@ -2027,10 +2027,9 @@ fn checkCompileErrors(compile: *Compile) !void {...@@ -2027,10 +2027,9 @@ fn checkCompileErrors(compile: *Compile) !void {
2027 var aw: std.Io.Writer.Allocating = .init(arena);2027 var aw: std.Io.Writer.Allocating = .init(arena);
2028 defer aw.deinit();2028 defer aw.deinit();
2029 try actual_eb.renderToWriter(.{2029 try actual_eb.renderToWriter(.{
2030 .ttyconf = .no_color,
2031 .include_reference_trace = false,2030 .include_reference_trace = false,
2032 .include_source_line = false,2031 .include_source_line = false,
2033 }, &aw.writer);2032 }, &aw.writer, .no_color);
2034 break :ae try aw.toOwnedSlice();2033 break :ae try aw.toOwnedSlice();
2035 };2034 };
20362035
lib/std/Build/WebServer.zig+4-5
...@@ -54,9 +54,9 @@ pub fn notifyUpdate(ws: *WebServer) void {...@@ -54,9 +54,9 @@ pub fn notifyUpdate(ws: *WebServer) void {
54pub const Options = struct {54pub const Options = struct {
55 gpa: Allocator,55 gpa: Allocator,
56 thread_pool: *std.Thread.Pool,56 thread_pool: *std.Thread.Pool,
57 ttyconf: Io.tty.Config,
57 graph: *const std.Build.Graph,58 graph: *const std.Build.Graph,
58 all_steps: []const *Build.Step,59 all_steps: []const *Build.Step,
59 ttyconf: Io.tty.Config,
60 root_prog_node: std.Progress.Node,60 root_prog_node: std.Progress.Node,
61 watch: bool,61 watch: bool,
62 listen_address: net.IpAddress,62 listen_address: net.IpAddress,
...@@ -101,10 +101,10 @@ pub fn init(opts: Options) WebServer {...@@ -101,10 +101,10 @@ pub fn init(opts: Options) WebServer {
101 return .{101 return .{
102 .gpa = opts.gpa,102 .gpa = opts.gpa,
103 .thread_pool = opts.thread_pool,103 .thread_pool = opts.thread_pool,
104 .ttyconf = opts.ttyconf,
104 .graph = opts.graph,105 .graph = opts.graph,
105 .all_steps = all_steps,106 .all_steps = all_steps,
106 .listen_address = opts.listen_address,107 .listen_address = opts.listen_address,
107 .ttyconf = opts.ttyconf,
108 .root_prog_node = opts.root_prog_node,108 .root_prog_node = opts.root_prog_node,
109 .watch = opts.watch,109 .watch = opts.watch,
110110
...@@ -236,9 +236,9 @@ pub fn finishBuild(ws: *WebServer, opts: struct {...@@ -236,9 +236,9 @@ pub fn finishBuild(ws: *WebServer, opts: struct {
236 ws.gpa,236 ws.gpa,
237 ws.graph.io,237 ws.graph.io,
238 ws.thread_pool,238 ws.thread_pool,
239 ws.ttyconf,
239 ws.all_steps,240 ws.all_steps,
240 ws.root_prog_node,241 ws.root_prog_node,
241 ws.ttyconf,
242 .{ .forever = .{ .ws = ws } },242 .{ .forever = .{ .ws = ws } },
243 ) catch |err| std.process.fatal("failed to start fuzzer: {s}", .{@errorName(err)});243 ) catch |err| std.process.fatal("failed to start fuzzer: {s}", .{@errorName(err)});
244 ws.fuzz.?.start();244 ws.fuzz.?.start();
...@@ -655,8 +655,7 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim...@@ -655,8 +655,7 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim
655 }655 }
656656
657 if (result_error_bundle.errorMessageCount() > 0) {657 if (result_error_bundle.errorMessageCount() > 0) {
658 const color = std.zig.Color.auto;658 result_error_bundle.renderToStdErr(.{}, .auto);
659 result_error_bundle.renderToStdErr(color.renderOptions());
660 log.err("the following command failed with {d} compilation errors:\n{s}", .{659 log.err("the following command failed with {d} compilation errors:\n{s}", .{
661 result_error_bundle.errorMessageCount(),660 result_error_bundle.errorMessageCount(),
662 try Build.Step.allocPrintCmd(arena, null, argv.items),661 try Build.Step.allocPrintCmd(arena, null, argv.items),
lib/std/debug.zig+19-19
...@@ -272,7 +272,7 @@ pub fn unlockStdErr() void {...@@ -272,7 +272,7 @@ pub fn unlockStdErr() void {
272 std.Progress.unlockStdErr();272 std.Progress.unlockStdErr();
273}273}
274274
275/// Allows the caller to freely write to stderr until `unlockStdErr` is called.275/// Allows the caller to freely write to stderr until `unlockStderrWriter` is called.
276///276///
277/// During the lock, any `std.Progress` information is cleared from the terminal.277/// During the lock, any `std.Progress` information is cleared from the terminal.
278///278///
...@@ -282,8 +282,16 @@ pub fn unlockStdErr() void {...@@ -282,8 +282,16 @@ pub fn unlockStdErr() void {
282///282///
283/// The returned `Writer` does not need to be manually flushed: flushing is performed automatically283/// The returned `Writer` does not need to be manually flushed: flushing is performed automatically
284/// when the matching `unlockStderrWriter` call occurs.284/// when the matching `unlockStderrWriter` call occurs.
285pub fn lockStderrWriter(buffer: []u8) *Writer {285pub fn lockStderrWriter(buffer: []u8) struct { *Writer, tty.Config } {
286 return std.Progress.lockStderrWriter(buffer);286 const global = struct {
287 var conf: ?tty.Config = null;
288 };
289 const w = std.Progress.lockStderrWriter(buffer);
290 // The stderr lock also locks access to `global.conf`.
291 if (global.conf == null) {
292 global.conf = .detect(.stderr());
293 }
294 return .{ w, global.conf.? };
287}295}
288296
289pub fn unlockStderrWriter() void {297pub fn unlockStderrWriter() void {
...@@ -297,7 +305,7 @@ pub fn unlockStderrWriter() void {...@@ -297,7 +305,7 @@ pub fn unlockStderrWriter() void {
297/// function returns.305/// function returns.
298pub fn print(comptime fmt: []const u8, args: anytype) void {306pub fn print(comptime fmt: []const u8, args: anytype) void {
299 var buffer: [64]u8 = undefined;307 var buffer: [64]u8 = undefined;
300 const bw = lockStderrWriter(&buffer);308 const bw, _ = lockStderrWriter(&buffer);
301 defer unlockStderrWriter();309 defer unlockStderrWriter();
302 nosuspend bw.print(fmt, args) catch return;310 nosuspend bw.print(fmt, args) catch return;
303}311}
...@@ -314,9 +322,8 @@ pub inline fn getSelfDebugInfo() !*SelfInfo {...@@ -314,9 +322,8 @@ pub inline fn getSelfDebugInfo() !*SelfInfo {
314/// Tries to print a hexadecimal view of the bytes, unbuffered, and ignores any error returned.322/// Tries to print a hexadecimal view of the bytes, unbuffered, and ignores any error returned.
315/// Obtains the stderr mutex while dumping.323/// Obtains the stderr mutex while dumping.
316pub fn dumpHex(bytes: []const u8) void {324pub fn dumpHex(bytes: []const u8) void {
317 const bw = lockStderrWriter(&.{});325 const bw, const ttyconf = lockStderrWriter(&.{});
318 defer unlockStderrWriter();326 defer unlockStderrWriter();
319 const ttyconf = tty.detectConfig(.stderr());
320 dumpHexFallible(bw, ttyconf, bytes) catch {};327 dumpHexFallible(bw, ttyconf, bytes) catch {};
321}328}
322329
...@@ -538,9 +545,7 @@ pub fn defaultPanic(...@@ -538,9 +545,7 @@ pub fn defaultPanic(
538 _ = panicking.fetchAdd(1, .seq_cst);545 _ = panicking.fetchAdd(1, .seq_cst);
539546
540 trace: {547 trace: {
541 const tty_config = tty.detectConfig(.stderr());548 const stderr, const tty_config = lockStderrWriter(&.{});
542
543 const stderr = lockStderrWriter(&.{});
544 defer unlockStderrWriter();549 defer unlockStderrWriter();
545550
546 if (builtin.single_threaded) {551 if (builtin.single_threaded) {
...@@ -743,8 +748,7 @@ pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, writer: *Wri...@@ -743,8 +748,7 @@ pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, writer: *Wri
743}748}
744/// A thin wrapper around `writeCurrentStackTrace` which writes to stderr and ignores write errors.749/// A thin wrapper around `writeCurrentStackTrace` which writes to stderr and ignores write errors.
745pub fn dumpCurrentStackTrace(options: StackUnwindOptions) void {750pub fn dumpCurrentStackTrace(options: StackUnwindOptions) void {
746 const tty_config = tty.detectConfig(.stderr());751 const stderr, const tty_config = lockStderrWriter(&.{});
747 const stderr = lockStderrWriter(&.{});
748 defer unlockStderrWriter();752 defer unlockStderrWriter();
749 writeCurrentStackTrace(.{753 writeCurrentStackTrace(.{
750 .first_address = a: {754 .first_address = a: {
...@@ -809,8 +813,7 @@ pub fn writeStackTrace(st: *const StackTrace, writer: *Writer, tty_config: tty.C...@@ -809,8 +813,7 @@ pub fn writeStackTrace(st: *const StackTrace, writer: *Writer, tty_config: tty.C
809}813}
810/// A thin wrapper around `writeStackTrace` which writes to stderr and ignores write errors.814/// A thin wrapper around `writeStackTrace` which writes to stderr and ignores write errors.
811pub fn dumpStackTrace(st: *const StackTrace) void {815pub fn dumpStackTrace(st: *const StackTrace) void {
812 const tty_config = tty.detectConfig(.stderr());816 const stderr, const tty_config = lockStderrWriter(&.{});
813 const stderr = lockStderrWriter(&.{});
814 defer unlockStderrWriter();817 defer unlockStderrWriter();
815 writeStackTrace(st, stderr, tty_config) catch |err| switch (err) {818 writeStackTrace(st, stderr, tty_config) catch |err| switch (err) {
816 error.WriteFailed => {},819 error.WriteFailed => {},
...@@ -1552,9 +1555,7 @@ pub fn defaultHandleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContex...@@ -1552,9 +1555,7 @@ pub fn defaultHandleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContex
1552 _ = panicking.fetchAdd(1, .seq_cst);1555 _ = panicking.fetchAdd(1, .seq_cst);
15531556
1554 trace: {1557 trace: {
1555 const tty_config = tty.detectConfig(.stderr());1558 const stderr, const tty_config = lockStderrWriter(&.{});
1556
1557 const stderr = lockStderrWriter(&.{});
1558 defer unlockStderrWriter();1559 defer unlockStderrWriter();
15591560
1560 if (addr) |a| {1561 if (addr) |a| {
...@@ -1612,7 +1613,7 @@ test "manage resources correctly" {...@@ -1612,7 +1613,7 @@ test "manage resources correctly" {
1612 &di,1613 &di,
1613 &discarding.writer,1614 &discarding.writer,
1614 S.showMyTrace(),1615 S.showMyTrace(),
1615 tty.detectConfig(.stderr()),1616 .no_color,
1616 );1617 );
1617}1618}
16181619
...@@ -1674,8 +1675,7 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize...@@ -1674,8 +1675,7 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize
1674 pub fn dump(t: @This()) void {1675 pub fn dump(t: @This()) void {
1675 if (!enabled) return;1676 if (!enabled) return;
16761677
1677 const tty_config = tty.detectConfig(.stderr());1678 const stderr, const tty_config = lockStderrWriter(&.{});
1678 const stderr = lockStderrWriter(&.{});
1679 defer unlockStderrWriter();1679 defer unlockStderrWriter();
1680 const end = @min(t.index, size);1680 const end = @min(t.index, size);
1681 for (t.addrs[0..end], 0..) |frames_array, i| {1681 for (t.addrs[0..end], 0..) |frames_array, i| {
lib/std/json/dynamic.zig+1-1
...@@ -47,7 +47,7 @@ pub const Value = union(enum) {...@@ -47,7 +47,7 @@ pub const Value = union(enum) {
47 }47 }
4848
49 pub fn dump(v: Value) void {49 pub fn dump(v: Value) void {
50 const w = std.debug.lockStderrWriter(&.{});50 const w, _ = std.debug.lockStderrWriter(&.{});
51 defer std.debug.unlockStderrWriter();51 defer std.debug.unlockStderrWriter();
5252
53 json.Stringify.value(v, .{}, w) catch return;53 json.Stringify.value(v, .{}, w) catch return;
lib/std/log.zig+1-1
...@@ -151,7 +151,7 @@ pub fn defaultLog(...@@ -151,7 +151,7 @@ pub fn defaultLog(
151 const level_txt = comptime message_level.asText();151 const level_txt = comptime message_level.asText();
152 const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): ";152 const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): ";
153 var buffer: [64]u8 = undefined;153 var buffer: [64]u8 = undefined;
154 const stderr = std.debug.lockStderrWriter(&buffer);154 const stderr, _ = std.debug.lockStderrWriter(&buffer);
155 defer std.debug.unlockStderrWriter();155 defer std.debug.unlockStderrWriter();
156 nosuspend stderr.print(level_txt ++ prefix2 ++ format ++ "\n", args) catch return;156 nosuspend stderr.print(level_txt ++ prefix2 ++ format ++ "\n", args) catch return;
157}157}
lib/std/testing.zig+4-4
...@@ -355,7 +355,7 @@ test expectApproxEqRel {...@@ -355,7 +355,7 @@ test expectApproxEqRel {
355/// This function is intended to be used only in tests. When the two slices are not355/// This function is intended to be used only in tests. When the two slices are not
356/// equal, prints diagnostics to stderr to show exactly how they are not equal (with356/// equal, prints diagnostics to stderr to show exactly how they are not equal (with
357/// the differences highlighted in red), then returns a test failure error.357/// the differences highlighted in red), then returns a test failure error.
358/// The colorized output is optional and controlled by the return of `std.Io.tty.detectConfig()`.358/// The colorized output is optional and controlled by the return of `std.Io.tty.Config.detect`.
359/// If your inputs are UTF-8 encoded strings, consider calling `expectEqualStrings` instead.359/// If your inputs are UTF-8 encoded strings, consider calling `expectEqualStrings` instead.
360pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const T) !void {360pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const T) !void {
361 const diff_index: usize = diff_index: {361 const diff_index: usize = diff_index: {
...@@ -367,9 +367,9 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const...@@ -367,9 +367,9 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const
367 break :diff_index if (expected.len == actual.len) return else shortest;367 break :diff_index if (expected.len == actual.len) return else shortest;
368 };368 };
369 if (!backend_can_print) return error.TestExpectedEqual;369 if (!backend_can_print) return error.TestExpectedEqual;
370 const stderr_w = std.debug.lockStderrWriter(&.{});370 const stderr_w, const ttyconf = std.debug.lockStderrWriter(&.{});
371 defer std.debug.unlockStderrWriter();371 defer std.debug.unlockStderrWriter();
372 failEqualSlices(T, expected, actual, diff_index, stderr_w) catch {};372 failEqualSlices(T, expected, actual, diff_index, stderr_w, ttyconf) catch {};
373 return error.TestExpectedEqual;373 return error.TestExpectedEqual;
374}374}
375375
...@@ -379,6 +379,7 @@ fn failEqualSlices(...@@ -379,6 +379,7 @@ fn failEqualSlices(
379 actual: []const T,379 actual: []const T,
380 diff_index: usize,380 diff_index: usize,
381 w: *std.Io.Writer,381 w: *std.Io.Writer,
382 ttyconf: std.Io.tty.Config,
382) !void {383) !void {
383 try w.print("slices differ. first difference occurs at index {d} (0x{X})\n", .{ diff_index, diff_index });384 try w.print("slices differ. first difference occurs at index {d} (0x{X})\n", .{ diff_index, diff_index });
384385
...@@ -398,7 +399,6 @@ fn failEqualSlices(...@@ -398,7 +399,6 @@ fn failEqualSlices(
398 const actual_window = actual[window_start..@min(actual.len, window_start + max_window_size)];399 const actual_window = actual[window_start..@min(actual.len, window_start + max_window_size)];
399 const actual_truncated = window_start + actual_window.len < actual.len;400 const actual_truncated = window_start + actual_window.len < actual.len;
400401
401 const ttyconf = std.Io.tty.detectConfig(.stderr());
402 var differ = if (T == u8) BytesDiffer{402 var differ = if (T == u8) BytesDiffer{
403 .expected = expected_window,403 .expected = expected_window,
404 .actual = actual_window,404 .actual = actual_window,
lib/std/zig.zig+8-7
...@@ -53,17 +53,18 @@ pub const Color = enum {...@@ -53,17 +53,18 @@ pub const Color = enum {
53 /// Assume stderr is a terminal.53 /// Assume stderr is a terminal.
54 on,54 on,
5555
56 pub fn get_tty_conf(color: Color) Io.tty.Config {56 pub fn getTtyConf(color: Color, detected: Io.tty.Config) Io.tty.Config {
57 return switch (color) {57 return switch (color) {
58 .auto => Io.tty.detectConfig(std.fs.File.stderr()),58 .auto => detected,
59 .on => .escape_codes,59 .on => .escape_codes,
60 .off => .no_color,60 .off => .no_color,
61 };61 };
62 }62 }
6363 pub fn detectTtyConf(color: Color) Io.tty.Config {
64 pub fn renderOptions(color: Color) std.zig.ErrorBundle.RenderOptions {64 return switch (color) {
65 return .{65 .auto => .detect(.stderr()),
66 .ttyconf = get_tty_conf(color),66 .on => .escape_codes,
67 .off => .no_color,
67 };68 };
68 }69 }
69};70};
...@@ -606,7 +607,7 @@ pub fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color...@@ -606,7 +607,7 @@ pub fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color
606607
607 var error_bundle = try wip_errors.toOwnedBundle("");608 var error_bundle = try wip_errors.toOwnedBundle("");
608 defer error_bundle.deinit(gpa);609 defer error_bundle.deinit(gpa);
609 error_bundle.renderToStdErr(color.renderOptions());610 error_bundle.renderToStdErr(.{}, color);
610}611}
611612
612pub fn putAstErrorsIntoBundle(613pub fn putAstErrorsIntoBundle(
lib/std/zig/ErrorBundle.zig+8-9
...@@ -157,23 +157,22 @@ pub fn nullTerminatedString(eb: ErrorBundle, index: String) [:0]const u8 {...@@ -157,23 +157,22 @@ pub fn nullTerminatedString(eb: ErrorBundle, index: String) [:0]const u8 {
157}157}
158158
159pub const RenderOptions = struct {159pub const RenderOptions = struct {
160 ttyconf: Io.tty.Config,
161 include_reference_trace: bool = true,160 include_reference_trace: bool = true,
162 include_source_line: bool = true,161 include_source_line: bool = true,
163 include_log_text: bool = true,162 include_log_text: bool = true,
164};163};
165164
166pub fn renderToStdErr(eb: ErrorBundle, options: RenderOptions) void {165pub fn renderToStdErr(eb: ErrorBundle, options: RenderOptions, color: std.zig.Color) void {
167 var buffer: [256]u8 = undefined;166 var buffer: [256]u8 = undefined;
168 const w = std.debug.lockStderrWriter(&buffer);167 const w, const ttyconf = std.debug.lockStderrWriter(&buffer);
169 defer std.debug.unlockStderrWriter();168 defer std.debug.unlockStderrWriter();
170 renderToWriter(eb, options, w) catch return;169 renderToWriter(eb, options, w, color.getTtyConf(ttyconf)) catch return;
171}170}
172171
173pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, w: *Writer) (Writer.Error || std.posix.UnexpectedError)!void {172pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, w: *Writer, ttyconf: Io.tty.Config) (Writer.Error || std.posix.UnexpectedError)!void {
174 if (eb.extra.len == 0) return;173 if (eb.extra.len == 0) return;
175 for (eb.getMessages()) |err_msg| {174 for (eb.getMessages()) |err_msg| {
176 try renderErrorMessageToWriter(eb, options, err_msg, w, "error", .red, 0);175 try renderErrorMessageToWriter(eb, options, err_msg, w, ttyconf, "error", .red, 0);
177 }176 }
178177
179 if (options.include_log_text) {178 if (options.include_log_text) {
...@@ -190,11 +189,11 @@ fn renderErrorMessageToWriter(...@@ -190,11 +189,11 @@ fn renderErrorMessageToWriter(
190 options: RenderOptions,189 options: RenderOptions,
191 err_msg_index: MessageIndex,190 err_msg_index: MessageIndex,
192 w: *Writer,191 w: *Writer,
192 ttyconf: Io.tty.Config,
193 kind: []const u8,193 kind: []const u8,
194 color: Io.tty.Color,194 color: Io.tty.Color,
195 indent: usize,195 indent: usize,
196) (Writer.Error || std.posix.UnexpectedError)!void {196) (Writer.Error || std.posix.UnexpectedError)!void {
197 const ttyconf = options.ttyconf;
198 const err_msg = eb.getErrorMessage(err_msg_index);197 const err_msg = eb.getErrorMessage(err_msg_index);
199 if (err_msg.src_loc != .none) {198 if (err_msg.src_loc != .none) {
200 const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc));199 const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc));
...@@ -251,7 +250,7 @@ fn renderErrorMessageToWriter(...@@ -251,7 +250,7 @@ fn renderErrorMessageToWriter(
251 try ttyconf.setColor(w, .reset);250 try ttyconf.setColor(w, .reset);
252 }251 }
253 for (eb.getNotes(err_msg_index)) |note| {252 for (eb.getNotes(err_msg_index)) |note| {
254 try renderErrorMessageToWriter(eb, options, note, w, "note", .cyan, indent);253 try renderErrorMessageToWriter(eb, options, note, w, ttyconf, "note", .cyan, indent);
255 }254 }
256 if (src.data.reference_trace_len > 0 and options.include_reference_trace) {255 if (src.data.reference_trace_len > 0 and options.include_reference_trace) {
257 try ttyconf.setColor(w, .reset);256 try ttyconf.setColor(w, .reset);
...@@ -300,7 +299,7 @@ fn renderErrorMessageToWriter(...@@ -300,7 +299,7 @@ fn renderErrorMessageToWriter(
300 }299 }
301 try ttyconf.setColor(w, .reset);300 try ttyconf.setColor(w, .reset);
302 for (eb.getNotes(err_msg_index)) |note| {301 for (eb.getNotes(err_msg_index)) |note| {
303 try renderErrorMessageToWriter(eb, options, note, w, "note", .cyan, indent + 4);302 try renderErrorMessageToWriter(eb, options, note, w, ttyconf, "note", .cyan, indent + 4);
304 }303 }
305 }304 }
306}305}
lib/std/zig/parser_test.zig+1-1
...@@ -6386,7 +6386,7 @@ var fixed_buffer_mem: [100 * 1024]u8 = undefined;...@@ -6386,7 +6386,7 @@ var fixed_buffer_mem: [100 * 1024]u8 = undefined;
63866386
6387fn testParse(source: [:0]const u8, allocator: mem.Allocator, anything_changed: *bool) ![]u8 {6387fn testParse(source: [:0]const u8, allocator: mem.Allocator, anything_changed: *bool) ![]u8 {
6388 var buffer: [64]u8 = undefined;6388 var buffer: [64]u8 = undefined;
6389 const stderr = std.debug.lockStderrWriter(&buffer);6389 const stderr, _ = std.debug.lockStderrWriter(&buffer);
6390 defer std.debug.unlockStderrWriter();6390 defer std.debug.unlockStderrWriter();
63916391
6392 var tree = try std.zig.Ast.parse(allocator, source, .zig);6392 var tree = try std.zig.Ast.parse(allocator, source, .zig);
src/Air/print.zig+2-2
...@@ -73,13 +73,13 @@ pub fn writeInst(...@@ -73,13 +73,13 @@ pub fn writeInst(
73}73}
7474
75pub fn dump(air: Air, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {75pub fn dump(air: Air, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {
76 const stderr_bw = std.debug.lockStderrWriter(&.{});76 const stderr_bw, _ = std.debug.lockStderrWriter(&.{});
77 defer std.debug.unlockStderrWriter();77 defer std.debug.unlockStderrWriter();
78 air.write(stderr_bw, pt, liveness);78 air.write(stderr_bw, pt, liveness);
79}79}
8080
81pub fn dumpInst(air: Air, inst: Air.Inst.Index, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {81pub fn dumpInst(air: Air, inst: Air.Inst.Index, pt: Zcu.PerThread, liveness: ?Air.Liveness) void {
82 const stderr_bw = std.debug.lockStderrWriter(&.{});82 const stderr_bw, _ = std.debug.lockStderrWriter(&.{});
83 defer std.debug.unlockStderrWriter();83 defer std.debug.unlockStderrWriter();
84 air.writeInst(stderr_bw, inst, pt, liveness);84 air.writeInst(stderr_bw, inst, pt, liveness);
85}85}
src/Compilation.zig+3-3
...@@ -2093,7 +2093,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -2093,7 +2093,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
20932093
2094 if (options.verbose_llvm_cpu_features) {2094 if (options.verbose_llvm_cpu_features) {
2095 if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: {2095 if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: {
2096 const stderr_w = std.debug.lockStderrWriter(&.{});2096 const stderr_w, _ = std.debug.lockStderrWriter(&.{});
2097 defer std.debug.unlockStderrWriter();2097 defer std.debug.unlockStderrWriter();
2098 stderr_w.print("compilation: {s}\n", .{options.root_name}) catch break :print;2098 stderr_w.print("compilation: {s}\n", .{options.root_name}) catch break :print;
2099 stderr_w.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print;2099 stderr_w.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print;
...@@ -4270,7 +4270,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle {...@@ -4270,7 +4270,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle {
4270 // However, we haven't reported any such error.4270 // However, we haven't reported any such error.
4271 // This is a compiler bug.4271 // This is a compiler bug.
4272 print_ctx: {4272 print_ctx: {
4273 var stderr_w = std.debug.lockStderrWriter(&.{});4273 var stderr_w, _ = std.debug.lockStderrWriter(&.{});
4274 defer std.debug.unlockStderrWriter();4274 defer std.debug.unlockStderrWriter();
4275 stderr_w.writeAll("referenced transitive analysis errors, but none actually emitted\n") catch break :print_ctx;4275 stderr_w.writeAll("referenced transitive analysis errors, but none actually emitted\n") catch break :print_ctx;
4276 stderr_w.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)}) catch break :print_ctx;4276 stderr_w.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)}) catch break :print_ctx;
...@@ -7752,7 +7752,7 @@ pub fn lockAndSetMiscFailure(...@@ -7752,7 +7752,7 @@ pub fn lockAndSetMiscFailure(
77527752
7753pub fn dump_argv(argv: []const []const u8) void {7753pub fn dump_argv(argv: []const []const u8) void {
7754 var buffer: [64]u8 = undefined;7754 var buffer: [64]u8 = undefined;
7755 const stderr = std.debug.lockStderrWriter(&buffer);7755 const stderr, _ = std.debug.lockStderrWriter(&buffer);
7756 defer std.debug.unlockStderrWriter();7756 defer std.debug.unlockStderrWriter();
7757 nosuspend {7757 nosuspend {
7758 for (argv, 0..) |arg, i| {7758 for (argv, 0..) |arg, i| {
src/InternPool.zig+2-2
...@@ -11330,7 +11330,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -11330,7 +11330,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
1133011330
11331fn dumpAllFallible(ip: *const InternPool) anyerror!void {11331fn dumpAllFallible(ip: *const InternPool) anyerror!void {
11332 var buffer: [4096]u8 = undefined;11332 var buffer: [4096]u8 = undefined;
11333 const stderr_bw = std.debug.lockStderrWriter(&buffer);11333 const stderr_bw, _ = std.debug.lockStderrWriter(&buffer);
11334 defer std.debug.unlockStderrWriter();11334 defer std.debug.unlockStderrWriter();
11335 for (ip.locals, 0..) |*local, tid| {11335 for (ip.locals, 0..) |*local, tid| {
11336 const items = local.shared.items.view();11336 const items = local.shared.items.view();
...@@ -11462,7 +11462,7 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)...@@ -11462,7 +11462,7 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)
11462 }11462 }
1146311463
11464 var buffer: [4096]u8 = undefined;11464 var buffer: [4096]u8 = undefined;
11465 const stderr_bw = std.debug.lockStderrWriter(&buffer);11465 const stderr_bw, _ = std.debug.lockStderrWriter(&buffer);
11466 defer std.debug.unlockStderrWriter();11466 defer std.debug.unlockStderrWriter();
1146711467
11468 const SortContext = struct {11468 const SortContext = struct {
src/Package/Fetch.zig+2-2
...@@ -2043,7 +2043,7 @@ const UnpackResult = struct {...@@ -2043,7 +2043,7 @@ const UnpackResult = struct {
2043 defer errors.deinit(gpa);2043 defer errors.deinit(gpa);
2044 var aw: Io.Writer.Allocating = .init(gpa);2044 var aw: Io.Writer.Allocating = .init(gpa);
2045 defer aw.deinit();2045 defer aw.deinit();
2046 try errors.renderToWriter(.{ .ttyconf = .no_color }, &aw.writer);2046 try errors.renderToWriter(.{}, &aw.writer, .no_color);
2047 try std.testing.expectEqualStrings(2047 try std.testing.expectEqualStrings(
2048 \\error: unable to unpack2048 \\error: unable to unpack
2049 \\ note: unable to create symlink from 'dir2/file2' to 'filename': SymlinkError2049 \\ note: unable to create symlink from 'dir2/file2' to 'filename': SymlinkError
...@@ -2360,7 +2360,7 @@ const TestFetchBuilder = struct {...@@ -2360,7 +2360,7 @@ const TestFetchBuilder = struct {
2360 }2360 }
2361 var aw: Io.Writer.Allocating = .init(std.testing.allocator);2361 var aw: Io.Writer.Allocating = .init(std.testing.allocator);
2362 defer aw.deinit();2362 defer aw.deinit();
2363 try errors.renderToWriter(.{ .ttyconf = .no_color }, &aw.writer);2363 try errors.renderToWriter(.{}, &aw.writer, .no_color);
2364 try std.testing.expectEqualStrings(msg, aw.written());2364 try std.testing.expectEqualStrings(msg, aw.written());
2365 }2365 }
2366};2366};
src/Sema.zig+1-1
...@@ -2631,7 +2631,7 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg...@@ -2631,7 +2631,7 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg
2631 Compilation.addModuleErrorMsg(zcu, &wip_errors, err_msg.*, false) catch @panic("out of memory");2631 Compilation.addModuleErrorMsg(zcu, &wip_errors, err_msg.*, false) catch @panic("out of memory");
2632 std.debug.print("compile error during Sema:\n", .{});2632 std.debug.print("compile error during Sema:\n", .{});
2633 var error_bundle = wip_errors.toOwnedBundle("") catch @panic("out of memory");2633 var error_bundle = wip_errors.toOwnedBundle("") catch @panic("out of memory");
2634 error_bundle.renderToStdErr(.{ .ttyconf = .no_color });2634 error_bundle.renderToStdErr(.{}, .auto);
2635 std.debug.panicExtra(@returnAddress(), "unexpected compile error occurred", .{});2635 std.debug.panicExtra(@returnAddress(), "unexpected compile error occurred", .{});
2636 }2636 }
26372637
src/Zcu/PerThread.zig+1-1
...@@ -4473,7 +4473,7 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e...@@ -4473,7 +4473,7 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e
4473 defer if (liveness) |*l| l.deinit(gpa);4473 defer if (liveness) |*l| l.deinit(gpa);
44744474
4475 if (build_options.enable_debug_extensions and comp.verbose_air) {4475 if (build_options.enable_debug_extensions and comp.verbose_air) {
4476 const stderr = std.debug.lockStderrWriter(&.{});4476 const stderr, _ = std.debug.lockStderrWriter(&.{});
4477 defer std.debug.unlockStderrWriter();4477 defer std.debug.unlockStderrWriter();
4478 stderr.print("# Begin Function AIR: {f}:\n", .{fqn.fmt(ip)}) catch {};4478 stderr.print("# Begin Function AIR: {f}:\n", .{fqn.fmt(ip)}) catch {};
4479 air.write(stderr, pt, liveness);4479 air.write(stderr, pt, liveness);
src/codegen/aarch64/Select.zig+1-1
...@@ -11188,7 +11188,7 @@ fn initValueAdvanced(...@@ -11188,7 +11188,7 @@ fn initValueAdvanced(
11188}11188}
11189pub fn dumpValues(isel: *Select, which: enum { only_referenced, all }) void {11189pub fn dumpValues(isel: *Select, which: enum { only_referenced, all }) void {
11190 errdefer |err| @panic(@errorName(err));11190 errdefer |err| @panic(@errorName(err));
11191 const stderr = std.debug.lockStderrWriter(&.{});11191 const stderr, _ = std.debug.lockStderrWriter(&.{});
11192 defer std.debug.unlockStderrWriter();11192 defer std.debug.unlockStderrWriter();
1119311193
11194 const zcu = isel.pt.zcu;11194 const zcu = isel.pt.zcu;
src/crash_report.zig+1-1
...@@ -95,7 +95,7 @@ fn dumpCrashContext() Io.Writer.Error!void {...@@ -95,7 +95,7 @@ fn dumpCrashContext() Io.Writer.Error!void {
9595
96 // TODO: this does mean that a different thread could grab the stderr mutex between the context96 // TODO: this does mean that a different thread could grab the stderr mutex between the context
97 // and the actual panic printing, which would be quite confusing.97 // and the actual panic printing, which would be quite confusing.
98 const stderr = std.debug.lockStderrWriter(&.{});98 const stderr, _ = std.debug.lockStderrWriter(&.{});
99 defer std.debug.unlockStderrWriter();99 defer std.debug.unlockStderrWriter();
100100
101 try stderr.writeAll("Compiler crash context:\n");101 try stderr.writeAll("Compiler crash context:\n");
src/fmt.zig+4-4
...@@ -124,7 +124,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !...@@ -124,7 +124,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !
124 try wip_errors.addZirErrorMessages(zir, tree, source_code, "<stdin>");124 try wip_errors.addZirErrorMessages(zir, tree, source_code, "<stdin>");
125 var error_bundle = try wip_errors.toOwnedBundle("");125 var error_bundle = try wip_errors.toOwnedBundle("");
126 defer error_bundle.deinit(gpa);126 defer error_bundle.deinit(gpa);
127 error_bundle.renderToStdErr(color.renderOptions());127 error_bundle.renderToStdErr(.{}, color);
128 process.exit(2);128 process.exit(2);
129 }129 }
130 } else {130 } else {
...@@ -138,7 +138,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !...@@ -138,7 +138,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !
138 try wip_errors.addZoirErrorMessages(zoir, tree, source_code, "<stdin>");138 try wip_errors.addZoirErrorMessages(zoir, tree, source_code, "<stdin>");
139 var error_bundle = try wip_errors.toOwnedBundle("");139 var error_bundle = try wip_errors.toOwnedBundle("");
140 defer error_bundle.deinit(gpa);140 defer error_bundle.deinit(gpa);
141 error_bundle.renderToStdErr(color.renderOptions());141 error_bundle.renderToStdErr(.{}, color);
142 process.exit(2);142 process.exit(2);
143 }143 }
144 }144 }
...@@ -317,7 +317,7 @@ fn fmtPathFile(...@@ -317,7 +317,7 @@ fn fmtPathFile(
317 try wip_errors.addZirErrorMessages(zir, tree, source_code, file_path);317 try wip_errors.addZirErrorMessages(zir, tree, source_code, file_path);
318 var error_bundle = try wip_errors.toOwnedBundle("");318 var error_bundle = try wip_errors.toOwnedBundle("");
319 defer error_bundle.deinit(gpa);319 defer error_bundle.deinit(gpa);
320 error_bundle.renderToStdErr(fmt.color.renderOptions());320 error_bundle.renderToStdErr(.{}, fmt.color);
321 fmt.any_error = true;321 fmt.any_error = true;
322 }322 }
323 },323 },
...@@ -332,7 +332,7 @@ fn fmtPathFile(...@@ -332,7 +332,7 @@ fn fmtPathFile(
332 try wip_errors.addZoirErrorMessages(zoir, tree, source_code, file_path);332 try wip_errors.addZoirErrorMessages(zoir, tree, source_code, file_path);
333 var error_bundle = try wip_errors.toOwnedBundle("");333 var error_bundle = try wip_errors.toOwnedBundle("");
334 defer error_bundle.deinit(gpa);334 defer error_bundle.deinit(gpa);
335 error_bundle.renderToStdErr(fmt.color.renderOptions());335 error_bundle.renderToStdErr(.{}, fmt.color);
336 fmt.any_error = true;336 fmt.any_error = true;
337 }337 }
338 },338 },
src/libs/mingw.zig+4-4
...@@ -312,7 +312,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -312,7 +312,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
312 const include_dir = try comp.dirs.zig_lib.join(arena, &.{ "libc", "mingw", "def-include" });312 const include_dir = try comp.dirs.zig_lib.join(arena, &.{ "libc", "mingw", "def-include" });
313313
314 if (comp.verbose_cc) print: {314 if (comp.verbose_cc) print: {
315 var stderr = std.debug.lockStderrWriter(&.{});315 var stderr, _ = std.debug.lockStderrWriter(&.{});
316 defer std.debug.unlockStderrWriter();316 defer std.debug.unlockStderrWriter();
317 nosuspend stderr.print("def file: {s}\n", .{def_file_path}) catch break :print;317 nosuspend stderr.print("def file: {s}\n", .{def_file_path}) catch break :print;
318 nosuspend stderr.print("include dir: {s}\n", .{include_dir}) catch break :print;318 nosuspend stderr.print("include dir: {s}\n", .{include_dir}) catch break :print;
...@@ -332,11 +332,11 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -332,11 +332,11 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
332332
333 if (aro_comp.diagnostics.output.to_list.messages.items.len != 0) {333 if (aro_comp.diagnostics.output.to_list.messages.items.len != 0) {
334 var buffer: [64]u8 = undefined;334 var buffer: [64]u8 = undefined;
335 const w = std.debug.lockStderrWriter(&buffer);335 const w, const ttyconf = std.debug.lockStderrWriter(&buffer);
336 defer std.debug.unlockStderrWriter();336 defer std.debug.unlockStderrWriter();
337 for (aro_comp.diagnostics.output.to_list.messages.items) |msg| {337 for (aro_comp.diagnostics.output.to_list.messages.items) |msg| {
338 if (msg.kind == .@"fatal error" or msg.kind == .@"error") {338 if (msg.kind == .@"fatal error" or msg.kind == .@"error") {
339 msg.write(w, .detect(std.fs.File.stderr()), true) catch {};339 msg.write(w, ttyconf, true) catch {};
340 return error.AroPreprocessorFailed;340 return error.AroPreprocessorFailed;
341 }341 }
342 }342 }
...@@ -356,7 +356,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -356,7 +356,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
356 error.OutOfMemory => |e| return e,356 error.OutOfMemory => |e| return e,
357 error.ParseError => {357 error.ParseError => {
358 var buffer: [64]u8 = undefined;358 var buffer: [64]u8 = undefined;
359 const w = std.debug.lockStderrWriter(&buffer);359 const w, _ = std.debug.lockStderrWriter(&buffer);
360 defer std.debug.unlockStderrWriter();360 defer std.debug.unlockStderrWriter();
361 try w.writeAll("error: ");361 try w.writeAll("error: ");
362 try def_diagnostics.writeMsg(w, input);362 try def_diagnostics.writeMsg(w, input);
src/libs/mingw/def.zig+1-1
...@@ -1028,7 +1028,7 @@ fn testParse(machine_type: std.coff.IMAGE.FILE.MACHINE, source: [:0]const u8, ex...@@ -1028,7 +1028,7 @@ fn testParse(machine_type: std.coff.IMAGE.FILE.MACHINE, source: [:0]const u8, ex
1028 const module = parse(std.testing.allocator, source, machine_type, .mingw, &diagnostics) catch |err| switch (err) {1028 const module = parse(std.testing.allocator, source, machine_type, .mingw, &diagnostics) catch |err| switch (err) {
1029 error.OutOfMemory => |e| return e,1029 error.OutOfMemory => |e| return e,
1030 error.ParseError => {1030 error.ParseError => {
1031 const stderr = std.debug.lockStderrWriter(&.{});1031 const stderr, _ = std.debug.lockStderrWriter(&.{});
1032 defer std.debug.unlockStderrWriter();1032 defer std.debug.unlockStderrWriter();
1033 try diagnostics.writeMsg(stderr, source);1033 try diagnostics.writeMsg(stderr, source);
1034 try stderr.writeByte('\n');1034 try stderr.writeByte('\n');
src/link.zig+1-1
...@@ -2215,7 +2215,7 @@ fn resolvePathInputLib(...@@ -2215,7 +2215,7 @@ fn resolvePathInputLib(
2215 var error_bundle = try wip_errors.toOwnedBundle("");2215 var error_bundle = try wip_errors.toOwnedBundle("");
2216 defer error_bundle.deinit(gpa);2216 defer error_bundle.deinit(gpa);
22172217
2218 error_bundle.renderToStdErr(color.renderOptions());2218 error_bundle.renderToStdErr(.{}, color);
22192219
2220 std.process.exit(1);2220 std.process.exit(1);
2221 }2221 }
src/link/Coff.zig+1-1
...@@ -2335,7 +2335,7 @@ pub fn deleteExport(coff: *Coff, exported: Zcu.Exported, name: InternPool.NullTe...@@ -2335,7 +2335,7 @@ pub fn deleteExport(coff: *Coff, exported: Zcu.Exported, name: InternPool.NullTe
2335}2335}
23362336
2337pub fn dump(coff: *Coff, tid: Zcu.PerThread.Id) void {2337pub fn dump(coff: *Coff, tid: Zcu.PerThread.Id) void {
2338 const w = std.debug.lockStderrWriter(&.{});2338 const w, _ = std.debug.lockStderrWriter(&.{});
2339 defer std.debug.unlockStderrWriter();2339 defer std.debug.unlockStderrWriter();
2340 coff.printNode(tid, w, .root, 0) catch {};2340 coff.printNode(tid, w, .root, 0) catch {};
2341}2341}
src/link/Elf2.zig+1-1
...@@ -1965,7 +1965,7 @@ pub fn deleteExport(elf: *Elf, exported: Zcu.Exported, name: InternPool.NullTerm...@@ -1965,7 +1965,7 @@ pub fn deleteExport(elf: *Elf, exported: Zcu.Exported, name: InternPool.NullTerm
1965}1965}
19661966
1967pub fn dump(elf: *Elf, tid: Zcu.PerThread.Id) void {1967pub fn dump(elf: *Elf, tid: Zcu.PerThread.Id) void {
1968 const w = std.debug.lockStderrWriter(&.{});1968 const w, _ = std.debug.lockStderrWriter(&.{});
1969 defer std.debug.unlockStderrWriter();1969 defer std.debug.unlockStderrWriter();
1970 elf.printNode(tid, w, .root, 0) catch {};1970 elf.printNode(tid, w, .root, 0) catch {};
1971}1971}
src/main.zig+9-9
...@@ -4520,7 +4520,7 @@ fn updateModule(comp: *Compilation, color: Color, prog_node: std.Progress.Node)...@@ -4520,7 +4520,7 @@ fn updateModule(comp: *Compilation, color: Color, prog_node: std.Progress.Node)
4520 defer errors.deinit(comp.gpa);4520 defer errors.deinit(comp.gpa);
45214521
4522 if (errors.errorMessageCount() > 0) {4522 if (errors.errorMessageCount() > 0) {
4523 errors.renderToStdErr(color.renderOptions());4523 errors.renderToStdErr(.{}, color);
4524 return error.CompileErrorsReported;4524 return error.CompileErrorsReported;
4525 }4525 }
4526}4526}
...@@ -4573,7 +4573,7 @@ fn cmdTranslateC(...@@ -4573,7 +4573,7 @@ fn cmdTranslateC(
4573 return;4573 return;
4574 } else {4574 } else {
4575 const color: Color = .auto;4575 const color: Color = .auto;
4576 result.errors.renderToStdErr(color.renderOptions());4576 result.errors.renderToStdErr(.{}, color);
4577 process.exit(1);4577 process.exit(1);
4578 }4578 }
4579 }4579 }
...@@ -5199,7 +5199,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8)...@@ -5199,7 +5199,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8)
51995199
5200 if (fetch.error_bundle.root_list.items.len > 0) {5200 if (fetch.error_bundle.root_list.items.len > 0) {
5201 var errors = try fetch.error_bundle.toOwnedBundle("");5201 var errors = try fetch.error_bundle.toOwnedBundle("");
5202 errors.renderToStdErr(color.renderOptions());5202 errors.renderToStdErr(.{}, color);
5203 process.exit(1);5203 process.exit(1);
5204 }5204 }
52055205
...@@ -6135,7 +6135,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void {...@@ -6135,7 +6135,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void {
6135 try wip_errors.init(arena);6135 try wip_errors.init(arena);
6136 try wip_errors.addZirErrorMessages(zir, tree, source, display_path);6136 try wip_errors.addZirErrorMessages(zir, tree, source, display_path);
6137 var error_bundle = try wip_errors.toOwnedBundle("");6137 var error_bundle = try wip_errors.toOwnedBundle("");
6138 error_bundle.renderToStdErr(color.renderOptions());6138 error_bundle.renderToStdErr(.{}, color);
6139 if (zir.loweringFailed()) {6139 if (zir.loweringFailed()) {
6140 process.exit(1);6140 process.exit(1);
6141 }6141 }
...@@ -6206,7 +6206,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void {...@@ -6206,7 +6206,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void {
6206 try wip_errors.init(arena);6206 try wip_errors.init(arena);
6207 try wip_errors.addZoirErrorMessages(zoir, tree, source, display_path);6207 try wip_errors.addZoirErrorMessages(zoir, tree, source, display_path);
6208 var error_bundle = try wip_errors.toOwnedBundle("");6208 var error_bundle = try wip_errors.toOwnedBundle("");
6209 error_bundle.renderToStdErr(color.renderOptions());6209 error_bundle.renderToStdErr(.{}, color);
6210 process.exit(1);6210 process.exit(1);
6211 }6211 }
62126212
...@@ -6479,7 +6479,7 @@ fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8) !void {...@@ -6479,7 +6479,7 @@ fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8) !void {
6479 try wip_errors.init(arena);6479 try wip_errors.init(arena);
6480 try wip_errors.addZirErrorMessages(old_zir, old_tree, old_source, old_source_path);6480 try wip_errors.addZirErrorMessages(old_zir, old_tree, old_source, old_source_path);
6481 var error_bundle = try wip_errors.toOwnedBundle("");6481 var error_bundle = try wip_errors.toOwnedBundle("");
6482 error_bundle.renderToStdErr(color.renderOptions());6482 error_bundle.renderToStdErr(.{}, color);
6483 process.exit(1);6483 process.exit(1);
6484 }6484 }
64856485
...@@ -6491,7 +6491,7 @@ fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8) !void {...@@ -6491,7 +6491,7 @@ fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8) !void {
6491 try wip_errors.init(arena);6491 try wip_errors.init(arena);
6492 try wip_errors.addZirErrorMessages(new_zir, new_tree, new_source, new_source_path);6492 try wip_errors.addZirErrorMessages(new_zir, new_tree, new_source, new_source_path);
6493 var error_bundle = try wip_errors.toOwnedBundle("");6493 var error_bundle = try wip_errors.toOwnedBundle("");
6494 error_bundle.renderToStdErr(color.renderOptions());6494 error_bundle.renderToStdErr(.{}, color);
6495 process.exit(1);6495 process.exit(1);
6496 }6496 }
64976497
...@@ -6948,7 +6948,7 @@ fn cmdFetch(...@@ -6948,7 +6948,7 @@ fn cmdFetch(
69486948
6949 if (fetch.error_bundle.root_list.items.len > 0) {6949 if (fetch.error_bundle.root_list.items.len > 0) {
6950 var errors = try fetch.error_bundle.toOwnedBundle("");6950 var errors = try fetch.error_bundle.toOwnedBundle("");
6951 errors.renderToStdErr(color.renderOptions());6951 errors.renderToStdErr(.{}, color);
6952 process.exit(1);6952 process.exit(1);
6953 }6953 }
69546954
...@@ -7304,7 +7304,7 @@ fn loadManifest(...@@ -7304,7 +7304,7 @@ fn loadManifest(
73047304
7305 var error_bundle = try wip_errors.toOwnedBundle("");7305 var error_bundle = try wip_errors.toOwnedBundle("");
7306 defer error_bundle.deinit(gpa);7306 defer error_bundle.deinit(gpa);
7307 error_bundle.renderToStdErr(options.color.renderOptions());7307 error_bundle.renderToStdErr(.{}, options.color);
73087308
7309 process.exit(2);7309 process.exit(2);
7310 }7310 }
tools/gen_spirv_spec.zig+3-4
...@@ -89,10 +89,9 @@ pub fn main() !void {...@@ -89,10 +89,9 @@ pub fn main() !void {
89 const output = allocating.written()[0 .. allocating.written().len - 1 :0];89 const output = allocating.written()[0 .. allocating.written().len - 1 :0];
9090
91 var tree = try std.zig.Ast.parse(allocator, output, .zig);91 var tree = try std.zig.Ast.parse(allocator, output, .zig);
92 var color: std.zig.Color = .on;
9392
94 if (tree.errors.len != 0) {93 if (tree.errors.len != 0) {
95 try std.zig.printAstErrorsToStderr(allocator, tree, "", color);94 try std.zig.printAstErrorsToStderr(allocator, tree, "", .auto);
96 return;95 return;
97 }96 }
9897
...@@ -104,7 +103,7 @@ pub fn main() !void {...@@ -104,7 +103,7 @@ pub fn main() !void {
104 try wip_errors.addZirErrorMessages(zir, tree, output, "");103 try wip_errors.addZirErrorMessages(zir, tree, output, "");
105 var error_bundle = try wip_errors.toOwnedBundle("");104 var error_bundle = try wip_errors.toOwnedBundle("");
106 defer error_bundle.deinit(allocator);105 defer error_bundle.deinit(allocator);
107 error_bundle.renderToStdErr(color.renderOptions());106 error_bundle.renderToStdErr(.{}, .auto);
108 }107 }
109108
110 const formatted_output = try tree.renderAlloc(allocator);109 const formatted_output = try tree.renderAlloc(allocator);
...@@ -931,7 +930,7 @@ fn parseHexInt(text: []const u8) !u31 {...@@ -931,7 +930,7 @@ fn parseHexInt(text: []const u8) !u31 {
931}930}
932931
933fn usageAndExit(arg0: []const u8, code: u8) noreturn {932fn usageAndExit(arg0: []const u8, code: u8) noreturn {
934 const stderr = std.debug.lockStderrWriter(&.{});933 const stderr, _ = std.debug.lockStderrWriter(&.{});
935 stderr.print(934 stderr.print(
936 \\Usage: {s} <SPIRV-Headers repository path> <path/to/zig/src/codegen/spirv/extinst.zig.grammar.json>935 \\Usage: {s} <SPIRV-Headers repository path> <path/to/zig/src/codegen/spirv/extinst.zig.grammar.json>
937 \\936 \\
tools/generate_linux_syscalls.zig+3-1
...@@ -177,7 +177,9 @@ pub fn main() !void {...@@ -177,7 +177,9 @@ pub fn main() !void {
177177
178 const args = try std.process.argsAlloc(gpa);178 const args = try std.process.argsAlloc(gpa);
179 if (args.len < 2 or mem.eql(u8, args[1], "--help")) {179 if (args.len < 2 or mem.eql(u8, args[1], "--help")) {
180 usage(std.debug.lockStderrWriter(&.{}), args[0]) catch std.process.exit(2);180 const w, _ = std.debug.lockStderrWriter(&.{});
181 defer std.debug.unlockStderrWriter();
182 usage(w, args[0]) catch std.process.exit(2);
181 std.process.exit(1);183 std.process.exit(1);
182 }184 }
183 const linux_path = args[1];185 const linux_path = args[1];
tools/incr-check.zig+5-10
...@@ -340,8 +340,7 @@ const Eval = struct {...@@ -340,8 +340,7 @@ const Eval = struct {
340 .unknown => return,340 .unknown => return,
341 .compile_errors => |ce| ce,341 .compile_errors => |ce| ce,
342 .stdout, .exit_code => {342 .stdout, .exit_code => {
343 const color: std.zig.Color = .auto;343 error_bundle.renderToStdErr(.{}, .auto);
344 error_bundle.renderToStdErr(color.renderOptions());
345 eval.fatal("update '{s}': unexpected compile errors", .{update.name});344 eval.fatal("update '{s}': unexpected compile errors", .{update.name});
346 },345 },
347 };346 };
...@@ -350,8 +349,7 @@ const Eval = struct {...@@ -350,8 +349,7 @@ const Eval = struct {
350349
351 for (error_bundle.getMessages()) |err_idx| {350 for (error_bundle.getMessages()) |err_idx| {
352 if (expected_idx == expected.errors.len) {351 if (expected_idx == expected.errors.len) {
353 const color: std.zig.Color = .auto;352 error_bundle.renderToStdErr(.{}, .auto);
354 error_bundle.renderToStdErr(color.renderOptions());
355 eval.fatal("update '{s}': more errors than expected", .{update.name});353 eval.fatal("update '{s}': more errors than expected", .{update.name});
356 }354 }
357 try eval.checkOneError(update, error_bundle, expected.errors[expected_idx], false, err_idx);355 try eval.checkOneError(update, error_bundle, expected.errors[expected_idx], false, err_idx);
...@@ -359,8 +357,7 @@ const Eval = struct {...@@ -359,8 +357,7 @@ const Eval = struct {
359357
360 for (error_bundle.getNotes(err_idx)) |note_idx| {358 for (error_bundle.getNotes(err_idx)) |note_idx| {
361 if (expected_idx == expected.errors.len) {359 if (expected_idx == expected.errors.len) {
362 const color: std.zig.Color = .auto;360 error_bundle.renderToStdErr(.{}, .auto);
363 error_bundle.renderToStdErr(color.renderOptions());
364 eval.fatal("update '{s}': more error notes than expected", .{update.name});361 eval.fatal("update '{s}': more error notes than expected", .{update.name});
365 }362 }
366 try eval.checkOneError(update, error_bundle, expected.errors[expected_idx], true, note_idx);363 try eval.checkOneError(update, error_bundle, expected.errors[expected_idx], true, note_idx);
...@@ -369,8 +366,7 @@ const Eval = struct {...@@ -369,8 +366,7 @@ const Eval = struct {
369 }366 }
370367
371 if (!std.mem.eql(u8, error_bundle.getCompileLogOutput(), expected.compile_log_output)) {368 if (!std.mem.eql(u8, error_bundle.getCompileLogOutput(), expected.compile_log_output)) {
372 const color: std.zig.Color = .auto;369 error_bundle.renderToStdErr(.{}, .auto);
373 error_bundle.renderToStdErr(color.renderOptions());
374 eval.fatal("update '{s}': unexpected compile log output", .{update.name});370 eval.fatal("update '{s}': unexpected compile log output", .{update.name});
375 }371 }
376 }372 }
...@@ -404,8 +400,7 @@ const Eval = struct {...@@ -404,8 +400,7 @@ const Eval = struct {
404 expected.column != src.column + 1 or400 expected.column != src.column + 1 or
405 !std.mem.eql(u8, expected.msg, msg))401 !std.mem.eql(u8, expected.msg, msg))
406 {402 {
407 const color: std.zig.Color = .auto;403 eb.renderToStdErr(.{}, .auto);
408 eb.renderToStdErr(color.renderOptions());
409 eval.fatal("update '{s}': compile error did not match expected error", .{update.name});404 eval.fatal("update '{s}': compile error did not match expected error", .{update.name});
410 }405 }
411 }406 }
tools/update_clang_options.zig+3-1
...@@ -961,7 +961,9 @@ fn objectLessThan(context: void, a: *json.ObjectMap, b: *json.ObjectMap) bool {...@@ -961,7 +961,9 @@ fn objectLessThan(context: void, a: *json.ObjectMap, b: *json.ObjectMap) bool {
961}961}
962962
963fn printUsageAndExit(arg0: []const u8) noreturn {963fn printUsageAndExit(arg0: []const u8) noreturn {
964 printUsage(std.debug.lockStderrWriter(&.{}), arg0) catch std.process.exit(2);964 const w, _ = std.debug.lockStderrWriter(&.{});
965 defer std.debug.unlockStderrWriter();
966 printUsage(w, arg0) catch std.process.exit(2);
965 std.process.exit(1);967 std.process.exit(1);
966}968}
967969
tools/update_cpu_features.zig+1-1
...@@ -2167,7 +2167,7 @@ fn processOneTarget(job: Job) void {...@@ -2167,7 +2167,7 @@ fn processOneTarget(job: Job) void {
2167}2167}
21682168
2169fn usageAndExit(arg0: []const u8, code: u8) noreturn {2169fn usageAndExit(arg0: []const u8, code: u8) noreturn {
2170 const stderr = std.debug.lockStderrWriter(&.{});2170 const stderr, _ = std.debug.lockStderrWriter(&.{});
2171 stderr.print(2171 stderr.print(
2172 \\Usage: {s} /path/to/llvm-tblgen /path/git/llvm-project /path/git/zig [zig_name filter]2172 \\Usage: {s} /path/to/llvm-tblgen /path/git/llvm-project /path/git/zig [zig_name filter]
2173 \\2173 \\
tools/update_crc_catalog.zig+3-1
...@@ -190,7 +190,9 @@ pub fn main() anyerror!void {...@@ -190,7 +190,9 @@ pub fn main() anyerror!void {
190}190}
191191
192fn printUsageAndExit(arg0: []const u8) noreturn {192fn printUsageAndExit(arg0: []const u8) noreturn {
193 printUsage(std.debug.lockStderrWriter(&.{}), arg0) catch std.process.exit(2);193 const w, _ = std.debug.lockStderrWriter(&.{});
194 defer std.debug.unlockStderrWriter();
195 printUsage(w, arg0) catch std.process.exit(2);
194 std.process.exit(1);196 std.process.exit(1);
195}197}
196198