From 74931fe25cdd94e1cd08b5ece9dcce19959bc079 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Tue, 28 Oct 2025 12:42:05 +0000 Subject: [PATCH] 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. --- lib/compiler/build_runner.zig | 41 ++++++++------------ lib/compiler/resinator/cli.zig | 6 +-- lib/compiler/resinator/errors.zig | 11 ++---- lib/compiler/resinator/main.zig | 63 ++++++++++++++----------------- lib/compiler/std-docs.zig | 3 +- lib/std/Build.zig | 12 +++--- lib/std/Build/Fuzz.zig | 18 ++++----- lib/std/Build/Step/Compile.zig | 11 +++--- lib/std/Build/WebServer.zig | 9 ++--- lib/std/debug.zig | 38 +++++++++---------- lib/std/json/dynamic.zig | 2 +- lib/std/log.zig | 2 +- lib/std/testing.zig | 8 ++-- lib/std/zig.zig | 15 ++++---- lib/std/zig/ErrorBundle.zig | 17 ++++----- lib/std/zig/parser_test.zig | 2 +- src/Air/print.zig | 4 +- src/Compilation.zig | 6 +-- src/InternPool.zig | 4 +- src/Package/Fetch.zig | 4 +- src/Sema.zig | 2 +- src/Zcu/PerThread.zig | 2 +- src/codegen/aarch64/Select.zig | 2 +- src/crash_report.zig | 2 +- src/fmt.zig | 8 ++-- src/libs/mingw.zig | 8 ++-- src/libs/mingw/def.zig | 2 +- src/link.zig | 2 +- src/link/Coff.zig | 2 +- src/link/Elf2.zig | 2 +- src/main.zig | 18 ++++----- tools/gen_spirv_spec.zig | 7 ++-- tools/generate_linux_syscalls.zig | 4 +- tools/incr-check.zig | 15 +++----- tools/update_clang_options.zig | 4 +- tools/update_cpu_features.zig | 2 +- tools/update_crc_catalog.zig | 4 +- 37 files changed, 169 insertions(+), 193 deletions(-) diff --git a/lib/compiler/build_runner.zig b/lib/compiler/build_runner.zig index 545cab6083..ae9eb53fb2 100644 --- a/lib/compiler/build_runner.zig +++ b/lib/compiler/build_runner.zig @@ -442,8 +442,7 @@ pub fn main() !void { if (builtin.single_threaded) fatal("'--webui' is not yet supported on single-threaded hosts", .{}); } - const stderr: std.fs.File = .stderr(); - const ttyconf = get_tty_conf(color, stderr); + const ttyconf = color.detectTtyConf(); switch (ttyconf) { .no_color => try graph.env_map.put("NO_COLOR", "1"), .escape_codes => try graph.env_map.put("CLICOLOR_FORCE", "1"), @@ -522,9 +521,9 @@ pub fn main() !void { .error_style = error_style, .multiline_errors = multiline_errors, .summary = summary orelse if (watch or webui_listen != null) .line else .failures, - .ttyconf = ttyconf, - .stderr = stderr, .thread_pool = undefined, + + .ttyconf = ttyconf, }; defer { run.memory_blocked_steps.deinit(gpa); @@ -563,9 +562,9 @@ pub fn main() !void { break :ws .init(.{ .gpa = gpa, .thread_pool = &run.thread_pool, + .ttyconf = ttyconf, .graph = &graph, .all_steps = run.step_stack.keys(), - .ttyconf = run.ttyconf, .root_prog_node = main_progress_node, .watch = watch, .listen_address = listen_address, @@ -578,7 +577,7 @@ pub fn main() !void { } rebuild: while (true) : (if (run.error_style.clearOnUpdate()) { - const bw = std.debug.lockStderrWriter(&stdio_buffer_allocation); + const bw, _ = std.debug.lockStderrWriter(&stdio_buffer_allocation); defer std.debug.unlockStderrWriter(); try bw.writeAll("\x1B[2J\x1B[3J\x1B[H"); }) { @@ -682,13 +681,14 @@ const Run = struct { /// Allocated into `gpa`. step_stack: std.AutoArrayHashMapUnmanaged(*Step, void), thread_pool: std.Thread.Pool, + /// Similar to the `tty.Config` returned by `std.debug.lockStderrWriter`, + /// but also respects the '--color' flag. + ttyconf: tty.Config, claimed_rss: usize, error_style: ErrorStyle, multiline_errors: MultilineErrors, summary: Summary, - ttyconf: tty.Config, - stderr: File, }; fn prepare( @@ -834,8 +834,6 @@ fn runStepNames( } } - const ttyconf = run.ttyconf; - if (fuzz) |mode| blk: { switch (builtin.os.tag) { // Current implementation depends on two things that need to be ported to Windows: @@ -863,9 +861,9 @@ fn runStepNames( gpa, io, thread_pool, + run.ttyconf, step_stack.keys(), parent_prog_node, - ttyconf, mode, ) catch |err| fatal("failed to start fuzzer: {s}", .{@errorName(err)}); defer f.deinit(); @@ -890,8 +888,9 @@ fn runStepNames( .none => break :summary, } - const w = std.debug.lockStderrWriter(&stdio_buffer_allocation); + const w, _ = std.debug.lockStderrWriter(&stdio_buffer_allocation); defer std.debug.unlockStderrWriter(); + const ttyconf = run.ttyconf; const total_count = success_count + failure_count + pending_count + skipped_count; ttyconf.setColor(w, .cyan) catch {}; @@ -1399,9 +1398,10 @@ fn workerMakeOneStep( const show_error_msgs = s.result_error_msgs.items.len > 0; const show_stderr = s.result_stderr.len > 0; if (show_error_msgs or show_compile_errors or show_stderr) { - const bw = std.debug.lockStderrWriter(&stdio_buffer_allocation); + const bw, _ = std.debug.lockStderrWriter(&stdio_buffer_allocation); defer std.debug.unlockStderrWriter(); - printErrorMessages(run.gpa, s, .{ .ttyconf = run.ttyconf }, bw, run.error_style, run.multiline_errors) catch {}; + const ttyconf = run.ttyconf; + printErrorMessages(run.gpa, s, .{}, bw, ttyconf, run.error_style, run.multiline_errors) catch {}; } handle_result: { @@ -1465,11 +1465,10 @@ pub fn printErrorMessages( failing_step: *Step, options: std.zig.ErrorBundle.RenderOptions, stderr: *Writer, + ttyconf: tty.Config, error_style: ErrorStyle, multiline_errors: MultilineErrors, ) !void { - const ttyconf = options.ttyconf; - if (error_style.verboseContext()) { // Provide context for where these error messages are coming from by // printing the corresponding Step subtree. @@ -1513,7 +1512,7 @@ pub fn printErrorMessages( } } - try failing_step.result_error_bundle.renderToWriter(options, stderr); + try failing_step.result_error_bundle.renderToWriter(options, stderr, ttyconf); for (failing_step.result_error_msgs.items) |msg| { try ttyconf.setColor(stderr, .red); @@ -1759,14 +1758,6 @@ const ErrorStyle = enum { const MultilineErrors = enum { indent, newline, none }; const Summary = enum { all, new, failures, line, none }; -fn get_tty_conf(color: Color, stderr: File) tty.Config { - return switch (color) { - .auto => tty.detectConfig(stderr), - .on => .escape_codes, - .off => .no_color, - }; -} - fn fatalWithHint(comptime f: []const u8, args: anytype) noreturn { std.debug.print(f ++ "\n access the help menu with 'zig build -h'\n", args); process.exit(1); diff --git a/lib/compiler/resinator/cli.zig b/lib/compiler/resinator/cli.zig index 2b31653cca..59568e9cef 100644 --- a/lib/compiler/resinator/cli.zig +++ b/lib/compiler/resinator/cli.zig @@ -124,10 +124,10 @@ pub const Diagnostics = struct { try self.errors.append(self.allocator, error_details); } - pub fn renderToStdErr(self: *Diagnostics, args: []const []const u8, config: std.Io.tty.Config) void { - const stderr = std.debug.lockStderrWriter(&.{}); + pub fn renderToStdErr(self: *Diagnostics, args: []const []const u8) void { + const stderr, const ttyconf = std.debug.lockStderrWriter(&.{}); defer std.debug.unlockStderrWriter(); - self.renderToWriter(args, stderr, config) catch return; + self.renderToWriter(args, stderr, ttyconf) catch return; } pub fn renderToWriter(self: *Diagnostics, args: []const []const u8, writer: *std.Io.Writer, config: std.Io.tty.Config) !void { diff --git a/lib/compiler/resinator/errors.zig b/lib/compiler/resinator/errors.zig index aad74a3ca3..f9ccc43a7f 100644 --- a/lib/compiler/resinator/errors.zig +++ b/lib/compiler/resinator/errors.zig @@ -67,20 +67,15 @@ pub const Diagnostics = struct { return @intCast(index); } - pub fn renderToStdErr(self: *Diagnostics, cwd: std.fs.Dir, source: []const u8, tty_config: std.Io.tty.Config, source_mappings: ?SourceMappings) void { + pub fn renderToStdErr(self: *Diagnostics, cwd: std.fs.Dir, source: []const u8, source_mappings: ?SourceMappings) void { const io = self.io; - const stderr = std.debug.lockStderrWriter(&.{}); + const stderr, const ttyconf = std.debug.lockStderrWriter(&.{}); defer std.debug.unlockStderrWriter(); for (self.errors.items) |err_details| { - renderErrorMessage(io, stderr, tty_config, cwd, err_details, source, self.strings.items, source_mappings) catch return; + renderErrorMessage(io, stderr, ttyconf, cwd, err_details, source, self.strings.items, source_mappings) catch return; } } - pub fn renderToStdErrDetectTTY(self: *Diagnostics, cwd: std.fs.Dir, source: []const u8, source_mappings: ?SourceMappings) void { - const tty_config = std.Io.tty.detectConfig(std.fs.File.stderr()); - return self.renderToStdErr(cwd, source, tty_config, source_mappings); - } - pub fn contains(self: *const Diagnostics, err: ErrorDetails.Error) bool { for (self.errors.items) |details| { if (details.err == err) return true; diff --git a/lib/compiler/resinator/main.zig b/lib/compiler/resinator/main.zig index b32237b06b..6d6819f45a 100644 --- a/lib/compiler/resinator/main.zig +++ b/lib/compiler/resinator/main.zig @@ -28,13 +28,11 @@ pub fn main() !void { defer arena_state.deinit(); const arena = arena_state.allocator(); - const stderr = std.fs.File.stderr(); - const stderr_config = std.Io.tty.detectConfig(stderr); - const args = try std.process.argsAlloc(arena); if (args.len < 2) { - try renderErrorMessage(std.debug.lockStderrWriter(&.{}), stderr_config, .err, "expected zig lib dir as first argument", .{}); + const w, const ttyconf = std.debug.lockStderrWriter(&.{}); + try renderErrorMessage(w, ttyconf, .err, "expected zig lib dir as first argument", .{}); std.process.exit(1); } const zig_lib_dir = args[1]; @@ -56,9 +54,7 @@ pub fn main() !void { .in = undefined, // won't be receiving messages }, }, - false => .{ - .tty = stderr_config, - }, + false => .stderr, }; var options = options: { @@ -75,12 +71,14 @@ pub fn main() !void { if (!zig_integration) { // print any warnings/notes - cli_diagnostics.renderToStdErr(cli_args, stderr_config); + cli_diagnostics.renderToStdErr(cli_args); // If there was something printed, then add an extra newline separator // so that there is a clear separation between the cli diagnostics and whatever // gets printed after if (cli_diagnostics.errors.items.len > 0) { - try stderr.writeAll("\n"); + const stderr, _ = std.debug.lockStderrWriter(&.{}); + defer std.debug.unlockStderrWriter(); + try stderr.writeByte('\n'); } } break :options options; @@ -130,17 +128,18 @@ pub fn main() !void { const aro_arena = aro_arena_state.allocator(); var stderr_buf: [512]u8 = undefined; - var stderr_writer = stderr.writer(&stderr_buf); - var diagnostics: aro.Diagnostics = switch (zig_integration) { - false => .{ .output = .{ .to_writer = .{ - .writer = &stderr_writer.interface, - .color = stderr_config, - } } }, - true => .{ .output = .{ .to_list = .{ - .arena = .init(gpa), - } } }, - }; - defer diagnostics.deinit(); + var diagnostics: aro.Diagnostics = .{ .output = output: { + if (zig_integration) break :output .{ .to_list = .{ .arena = .init(gpa) } }; + const w, const ttyconf = std.debug.lockStderrWriter(&stderr_buf); + break :output .{ .to_writer = .{ + .writer = w, + .color = ttyconf, + } }; + } }; + defer { + diagnostics.deinit(); + if (!zig_integration) std.debug.unlockStderrWriter(); + } var comp = aro.Compilation.init(aro_arena, aro_arena, io, &diagnostics, std.fs.cwd()); defer comp.deinit(); @@ -307,7 +306,7 @@ pub fn main() !void { // print any warnings/notes if (!zig_integration) { - diagnostics.renderToStdErr(std.fs.cwd(), final_input, stderr_config, mapping_results.mappings); + diagnostics.renderToStdErr(std.fs.cwd(), final_input, mapping_results.mappings); } // write the depfile @@ -660,7 +659,7 @@ const SourceMappings = @import("source_mapping.zig").SourceMappings; const ErrorHandler = union(enum) { server: std.zig.Server, - tty: std.Io.tty.Config, + stderr, pub fn emitCliDiagnostics( self: *ErrorHandler, @@ -675,9 +674,7 @@ const ErrorHandler = union(enum) { try server.serveErrorBundle(error_bundle); }, - .tty => { - diagnostics.renderToStdErr(args, self.tty); - }, + .stderr => diagnostics.renderToStdErr(args), } } @@ -698,11 +695,11 @@ const ErrorHandler = union(enum) { try server.serveErrorBundle(error_bundle); }, - .tty => { + .stderr => { // aro errors have already been emitted - const stderr = std.debug.lockStderrWriter(&.{}); + const stderr, const ttyconf = std.debug.lockStderrWriter(&.{}); defer std.debug.unlockStderrWriter(); - try renderErrorMessage(stderr, self.tty, .err, "{s}", .{fail_msg}); + try renderErrorMessage(stderr, ttyconf, .err, "{s}", .{fail_msg}); }, } } @@ -722,9 +719,7 @@ const ErrorHandler = union(enum) { try server.serveErrorBundle(error_bundle); }, - .tty => { - diagnostics.renderToStdErr(cwd, source, self.tty, mappings); - }, + .stderr => diagnostics.renderToStdErr(cwd, source, mappings), } } @@ -745,10 +740,10 @@ const ErrorHandler = union(enum) { try server.serveErrorBundle(error_bundle); }, - .tty => { - const stderr = std.debug.lockStderrWriter(&.{}); + .stderr => { + const stderr, const ttyconf = std.debug.lockStderrWriter(&.{}); defer std.debug.unlockStderrWriter(); - try renderErrorMessage(stderr, self.tty, msg_type, format, args); + try renderErrorMessage(stderr, ttyconf, msg_type, format, args); }, } } diff --git a/lib/compiler/std-docs.zig b/lib/compiler/std-docs.zig index e80c3d3dcd..f560e05cca 100644 --- a/lib/compiler/std-docs.zig +++ b/lib/compiler/std-docs.zig @@ -394,8 +394,7 @@ fn buildWasmBinary( } if (result_error_bundle.errorMessageCount() > 0) { - const color = std.zig.Color.auto; - result_error_bundle.renderToStdErr(color.renderOptions()); + result_error_bundle.renderToStdErr(.{}, true); std.log.err("the following command failed with {d} compilation errors:\n{s}", .{ result_error_bundle.errorMessageCount(), try std.Build.Step.allocPrintCmd(arena, null, argv.items), diff --git a/lib/std/Build.zig b/lib/std/Build.zig index e9d2e81fba..3b78fc6f71 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -2257,8 +2257,8 @@ pub const GeneratedFile = struct { pub fn getPath2(gen: GeneratedFile, src_builder: *Build, asking_step: ?*Step) []const u8 { return gen.path orelse { - const w = debug.lockStderrWriter(&.{}); - dumpBadGetPathHelp(gen.step, w, .detect(.stderr()), src_builder, asking_step) catch {}; + const w, const ttyconf = debug.lockStderrWriter(&.{}); + dumpBadGetPathHelp(gen.step, w, ttyconf, src_builder, asking_step) catch {}; debug.unlockStderrWriter(); @panic("misconfigured build script"); }; @@ -2466,8 +2466,8 @@ pub const LazyPath = union(enum) { var file_path: Cache.Path = .{ .root_dir = Cache.Directory.cwd(), .sub_path = gen.file.path orelse { - const w = debug.lockStderrWriter(&.{}); - dumpBadGetPathHelp(gen.file.step, w, .detect(.stderr()), src_builder, asking_step) catch {}; + const w, const ttyconf = debug.lockStderrWriter(&.{}); + dumpBadGetPathHelp(gen.file.step, w, ttyconf, src_builder, asking_step) catch {}; debug.unlockStderrWriter(); @panic("misconfigured build script"); }, @@ -2558,13 +2558,11 @@ fn dumpBadDirnameHelp( comptime msg: []const u8, args: anytype, ) anyerror!void { - const w = debug.lockStderrWriter(&.{}); + const w, const tty_config = debug.lockStderrWriter(&.{}); defer debug.unlockStderrWriter(); try w.print(msg, args); - const tty_config = std.Io.tty.detectConfig(.stderr()); - if (fail_step) |s| { tty_config.setColor(w, .red) catch {}; try w.writeAll(" The step was created by this stack trace:\n"); diff --git a/lib/std/Build/Fuzz.zig b/lib/std/Build/Fuzz.zig index d342628871..6dd4f70f9f 100644 --- a/lib/std/Build/Fuzz.zig +++ b/lib/std/Build/Fuzz.zig @@ -16,6 +16,7 @@ const build_runner = @import("root"); gpa: Allocator, io: Io, +ttyconf: tty.Config, mode: Mode, /// Allocated into `gpa`. @@ -25,7 +26,6 @@ wait_group: std.Thread.WaitGroup, root_prog_node: std.Progress.Node, prog_node: std.Progress.Node, thread_pool: *std.Thread.Pool, -ttyconf: tty.Config, /// Protects `coverage_files`. coverage_mutex: std.Thread.Mutex, @@ -79,9 +79,9 @@ pub fn init( gpa: Allocator, io: Io, thread_pool: *std.Thread.Pool, + ttyconf: tty.Config, all_steps: []const *Build.Step, root_prog_node: std.Progress.Node, - ttyconf: tty.Config, mode: Mode, ) Allocator.Error!Fuzz { const run_steps: []const *Step.Run = steps: { @@ -115,11 +115,11 @@ pub fn init( return .{ .gpa = gpa, .io = io, + .ttyconf = ttyconf, .mode = mode, .run_steps = run_steps, .wait_group = .{}, .thread_pool = thread_pool, - .ttyconf = ttyconf, .root_prog_node = root_prog_node, .prog_node = .none, .coverage_files = .empty, @@ -158,7 +158,7 @@ pub fn deinit(fuzz: *Fuzz) void { fuzz.gpa.free(fuzz.run_steps); } -fn rebuildTestsWorkerRun(run: *Step.Run, gpa: Allocator, ttyconf: std.Io.tty.Config, parent_prog_node: std.Progress.Node) void { +fn rebuildTestsWorkerRun(run: *Step.Run, gpa: Allocator, ttyconf: tty.Config, parent_prog_node: std.Progress.Node) void { rebuildTestsWorkerRunFallible(run, gpa, ttyconf, parent_prog_node) catch |err| { const compile = run.producer.?; 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 }; } -fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, ttyconf: std.Io.tty.Config, parent_prog_node: std.Progress.Node) !void { +fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, ttyconf: tty.Config, parent_prog_node: std.Progress.Node) !void { const compile = run.producer.?; const prog_node = parent_prog_node.start(compile.step.name, 0); defer prog_node.end(); @@ -180,9 +180,9 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, gpa: Allocator, ttyconf: std.Io if (show_error_msgs or show_compile_errors or show_stderr) { var buf: [256]u8 = undefined; - const w = std.debug.lockStderrWriter(&buf); + const w, _ = std.debug.lockStderrWriter(&buf); defer std.debug.unlockStderrWriter(); - build_runner.printErrorMessages(gpa, &compile.step, .{ .ttyconf = ttyconf }, w, .verbose, .indent) catch {}; + build_runner.printErrorMessages(gpa, &compile.step, .{}, w, ttyconf, .verbose, .indent) catch {}; } const rebuilt_bin_path = result catch |err| switch (err) { @@ -206,9 +206,9 @@ fn fuzzWorkerRun( run.rerunInFuzzMode(fuzz, unit_test_index, prog_node) catch |err| switch (err) { error.MakeFailed => { var buf: [256]u8 = undefined; - const w = std.debug.lockStderrWriter(&buf); + const w, _ = std.debug.lockStderrWriter(&buf); defer std.debug.unlockStderrWriter(); - build_runner.printErrorMessages(gpa, &run.step, .{ .ttyconf = fuzz.ttyconf }, w, .verbose, .indent) catch {}; + build_runner.printErrorMessages(gpa, &run.step, .{}, w, fuzz.ttyconf, .verbose, .indent) catch {}; return; }, else => { diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index 2188d8bfc7..a5f2d696be 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -1056,15 +1056,15 @@ fn getGeneratedFilePath(compile: *Compile, comptime tag_name: []const u8, asking const maybe_path: ?*GeneratedFile = @field(compile, tag_name); const generated_file = maybe_path orelse { - const w = std.debug.lockStderrWriter(&.{}); - std.Build.dumpBadGetPathHelp(&compile.step, w, .detect(.stderr()), compile.step.owner, asking_step) catch {}; + const w, const ttyconf = std.debug.lockStderrWriter(&.{}); + std.Build.dumpBadGetPathHelp(&compile.step, w, ttyconf, compile.step.owner, asking_step) catch {}; std.debug.unlockStderrWriter(); @panic("missing emit option for " ++ tag_name); }; const path = generated_file.path orelse { - const w = std.debug.lockStderrWriter(&.{}); - std.Build.dumpBadGetPathHelp(&compile.step, w, .detect(.stderr()), compile.step.owner, asking_step) catch {}; + const w, const ttyconf = std.debug.lockStderrWriter(&.{}); + std.Build.dumpBadGetPathHelp(&compile.step, w, ttyconf, compile.step.owner, asking_step) catch {}; std.debug.unlockStderrWriter(); @panic(tag_name ++ " is null. Is there a missing step dependency?"); }; @@ -2027,10 +2027,9 @@ fn checkCompileErrors(compile: *Compile) !void { var aw: std.Io.Writer.Allocating = .init(arena); defer aw.deinit(); try actual_eb.renderToWriter(.{ - .ttyconf = .no_color, .include_reference_trace = false, .include_source_line = false, - }, &aw.writer); + }, &aw.writer, .no_color); break :ae try aw.toOwnedSlice(); }; diff --git a/lib/std/Build/WebServer.zig b/lib/std/Build/WebServer.zig index 50e304c950..4a136ccbf4 100644 --- a/lib/std/Build/WebServer.zig +++ b/lib/std/Build/WebServer.zig @@ -54,9 +54,9 @@ pub fn notifyUpdate(ws: *WebServer) void { pub const Options = struct { gpa: Allocator, thread_pool: *std.Thread.Pool, + ttyconf: Io.tty.Config, graph: *const std.Build.Graph, all_steps: []const *Build.Step, - ttyconf: Io.tty.Config, root_prog_node: std.Progress.Node, watch: bool, listen_address: net.IpAddress, @@ -101,10 +101,10 @@ pub fn init(opts: Options) WebServer { return .{ .gpa = opts.gpa, .thread_pool = opts.thread_pool, + .ttyconf = opts.ttyconf, .graph = opts.graph, .all_steps = all_steps, .listen_address = opts.listen_address, - .ttyconf = opts.ttyconf, .root_prog_node = opts.root_prog_node, .watch = opts.watch, @@ -236,9 +236,9 @@ pub fn finishBuild(ws: *WebServer, opts: struct { ws.gpa, ws.graph.io, ws.thread_pool, + ws.ttyconf, ws.all_steps, ws.root_prog_node, - ws.ttyconf, .{ .forever = .{ .ws = ws } }, ) catch |err| std.process.fatal("failed to start fuzzer: {s}", .{@errorName(err)}); ws.fuzz.?.start(); @@ -655,8 +655,7 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim } if (result_error_bundle.errorMessageCount() > 0) { - const color = std.zig.Color.auto; - result_error_bundle.renderToStdErr(color.renderOptions()); + result_error_bundle.renderToStdErr(.{}, .auto); log.err("the following command failed with {d} compilation errors:\n{s}", .{ result_error_bundle.errorMessageCount(), try Build.Step.allocPrintCmd(arena, null, argv.items), diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 3bb5d6d7ab..19b3a3c2fb 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -272,7 +272,7 @@ pub fn unlockStdErr() void { std.Progress.unlockStdErr(); } -/// Allows the caller to freely write to stderr until `unlockStdErr` is called. +/// Allows the caller to freely write to stderr until `unlockStderrWriter` is called. /// /// During the lock, any `std.Progress` information is cleared from the terminal. /// @@ -282,8 +282,16 @@ pub fn unlockStdErr() void { /// /// The returned `Writer` does not need to be manually flushed: flushing is performed automatically /// when the matching `unlockStderrWriter` call occurs. -pub fn lockStderrWriter(buffer: []u8) *Writer { - return std.Progress.lockStderrWriter(buffer); +pub fn lockStderrWriter(buffer: []u8) struct { *Writer, tty.Config } { + const global = struct { + var conf: ?tty.Config = null; + }; + const w = std.Progress.lockStderrWriter(buffer); + // The stderr lock also locks access to `global.conf`. + if (global.conf == null) { + global.conf = .detect(.stderr()); + } + return .{ w, global.conf.? }; } pub fn unlockStderrWriter() void { @@ -297,7 +305,7 @@ pub fn unlockStderrWriter() void { /// function returns. pub fn print(comptime fmt: []const u8, args: anytype) void { var buffer: [64]u8 = undefined; - const bw = lockStderrWriter(&buffer); + const bw, _ = lockStderrWriter(&buffer); defer unlockStderrWriter(); nosuspend bw.print(fmt, args) catch return; } @@ -314,9 +322,8 @@ pub inline fn getSelfDebugInfo() !*SelfInfo { /// Tries to print a hexadecimal view of the bytes, unbuffered, and ignores any error returned. /// Obtains the stderr mutex while dumping. pub fn dumpHex(bytes: []const u8) void { - const bw = lockStderrWriter(&.{}); + const bw, const ttyconf = lockStderrWriter(&.{}); defer unlockStderrWriter(); - const ttyconf = tty.detectConfig(.stderr()); dumpHexFallible(bw, ttyconf, bytes) catch {}; } @@ -538,9 +545,7 @@ pub fn defaultPanic( _ = panicking.fetchAdd(1, .seq_cst); trace: { - const tty_config = tty.detectConfig(.stderr()); - - const stderr = lockStderrWriter(&.{}); + const stderr, const tty_config = lockStderrWriter(&.{}); defer unlockStderrWriter(); if (builtin.single_threaded) { @@ -743,8 +748,7 @@ pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, writer: *Wri } /// A thin wrapper around `writeCurrentStackTrace` which writes to stderr and ignores write errors. pub fn dumpCurrentStackTrace(options: StackUnwindOptions) void { - const tty_config = tty.detectConfig(.stderr()); - const stderr = lockStderrWriter(&.{}); + const stderr, const tty_config = lockStderrWriter(&.{}); defer unlockStderrWriter(); writeCurrentStackTrace(.{ .first_address = a: { @@ -809,8 +813,7 @@ pub fn writeStackTrace(st: *const StackTrace, writer: *Writer, tty_config: tty.C } /// A thin wrapper around `writeStackTrace` which writes to stderr and ignores write errors. pub fn dumpStackTrace(st: *const StackTrace) void { - const tty_config = tty.detectConfig(.stderr()); - const stderr = lockStderrWriter(&.{}); + const stderr, const tty_config = lockStderrWriter(&.{}); defer unlockStderrWriter(); writeStackTrace(st, stderr, tty_config) catch |err| switch (err) { error.WriteFailed => {}, @@ -1552,9 +1555,7 @@ pub fn defaultHandleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContex _ = panicking.fetchAdd(1, .seq_cst); trace: { - const tty_config = tty.detectConfig(.stderr()); - - const stderr = lockStderrWriter(&.{}); + const stderr, const tty_config = lockStderrWriter(&.{}); defer unlockStderrWriter(); if (addr) |a| { @@ -1612,7 +1613,7 @@ test "manage resources correctly" { &di, &discarding.writer, S.showMyTrace(), - tty.detectConfig(.stderr()), + .no_color, ); } @@ -1674,8 +1675,7 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize pub fn dump(t: @This()) void { if (!enabled) return; - const tty_config = tty.detectConfig(.stderr()); - const stderr = lockStderrWriter(&.{}); + const stderr, const tty_config = lockStderrWriter(&.{}); defer unlockStderrWriter(); const end = @min(t.index, size); for (t.addrs[0..end], 0..) |frames_array, i| { diff --git a/lib/std/json/dynamic.zig b/lib/std/json/dynamic.zig index 8aacf42865..c3cccd1a91 100644 --- a/lib/std/json/dynamic.zig +++ b/lib/std/json/dynamic.zig @@ -47,7 +47,7 @@ pub const Value = union(enum) { } pub fn dump(v: Value) void { - const w = std.debug.lockStderrWriter(&.{}); + const w, _ = std.debug.lockStderrWriter(&.{}); defer std.debug.unlockStderrWriter(); json.Stringify.value(v, .{}, w) catch return; diff --git a/lib/std/log.zig b/lib/std/log.zig index 113831e462..1b1c98dd43 100644 --- a/lib/std/log.zig +++ b/lib/std/log.zig @@ -151,7 +151,7 @@ pub fn defaultLog( const level_txt = comptime message_level.asText(); const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): "; var buffer: [64]u8 = undefined; - const stderr = std.debug.lockStderrWriter(&buffer); + const stderr, _ = std.debug.lockStderrWriter(&buffer); defer std.debug.unlockStderrWriter(); nosuspend stderr.print(level_txt ++ prefix2 ++ format ++ "\n", args) catch return; } diff --git a/lib/std/testing.zig b/lib/std/testing.zig index 7cef6f9c58..b99542e7e5 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -355,7 +355,7 @@ test expectApproxEqRel { /// This function is intended to be used only in tests. When the two slices are not /// equal, prints diagnostics to stderr to show exactly how they are not equal (with /// the differences highlighted in red), then returns a test failure error. -/// The colorized output is optional and controlled by the return of `std.Io.tty.detectConfig()`. +/// The colorized output is optional and controlled by the return of `std.Io.tty.Config.detect`. /// If your inputs are UTF-8 encoded strings, consider calling `expectEqualStrings` instead. pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const T) !void { const diff_index: usize = diff_index: { @@ -367,9 +367,9 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const break :diff_index if (expected.len == actual.len) return else shortest; }; if (!backend_can_print) return error.TestExpectedEqual; - const stderr_w = std.debug.lockStderrWriter(&.{}); + const stderr_w, const ttyconf = std.debug.lockStderrWriter(&.{}); defer std.debug.unlockStderrWriter(); - failEqualSlices(T, expected, actual, diff_index, stderr_w) catch {}; + failEqualSlices(T, expected, actual, diff_index, stderr_w, ttyconf) catch {}; return error.TestExpectedEqual; } @@ -379,6 +379,7 @@ fn failEqualSlices( actual: []const T, diff_index: usize, w: *std.Io.Writer, + ttyconf: std.Io.tty.Config, ) !void { try w.print("slices differ. first difference occurs at index {d} (0x{X})\n", .{ diff_index, diff_index }); @@ -398,7 +399,6 @@ fn failEqualSlices( const actual_window = actual[window_start..@min(actual.len, window_start + max_window_size)]; const actual_truncated = window_start + actual_window.len < actual.len; - const ttyconf = std.Io.tty.detectConfig(.stderr()); var differ = if (T == u8) BytesDiffer{ .expected = expected_window, .actual = actual_window, diff --git a/lib/std/zig.zig b/lib/std/zig.zig index 34851709ab..dcdc727ae2 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -53,17 +53,18 @@ pub const Color = enum { /// Assume stderr is a terminal. on, - pub fn get_tty_conf(color: Color) Io.tty.Config { + pub fn getTtyConf(color: Color, detected: Io.tty.Config) Io.tty.Config { return switch (color) { - .auto => Io.tty.detectConfig(std.fs.File.stderr()), + .auto => detected, .on => .escape_codes, .off => .no_color, }; } - - pub fn renderOptions(color: Color) std.zig.ErrorBundle.RenderOptions { - return .{ - .ttyconf = get_tty_conf(color), + pub fn detectTtyConf(color: Color) Io.tty.Config { + return switch (color) { + .auto => .detect(.stderr()), + .on => .escape_codes, + .off => .no_color, }; } }; @@ -606,7 +607,7 @@ pub fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color var error_bundle = try wip_errors.toOwnedBundle(""); defer error_bundle.deinit(gpa); - error_bundle.renderToStdErr(color.renderOptions()); + error_bundle.renderToStdErr(.{}, color); } pub fn putAstErrorsIntoBundle( diff --git a/lib/std/zig/ErrorBundle.zig b/lib/std/zig/ErrorBundle.zig index 2b2ad396de..bcef7f407c 100644 --- a/lib/std/zig/ErrorBundle.zig +++ b/lib/std/zig/ErrorBundle.zig @@ -157,23 +157,22 @@ pub fn nullTerminatedString(eb: ErrorBundle, index: String) [:0]const u8 { } pub const RenderOptions = struct { - ttyconf: Io.tty.Config, include_reference_trace: bool = true, include_source_line: bool = true, include_log_text: bool = true, }; -pub fn renderToStdErr(eb: ErrorBundle, options: RenderOptions) void { +pub fn renderToStdErr(eb: ErrorBundle, options: RenderOptions, color: std.zig.Color) void { var buffer: [256]u8 = undefined; - const w = std.debug.lockStderrWriter(&buffer); + const w, const ttyconf = std.debug.lockStderrWriter(&buffer); defer std.debug.unlockStderrWriter(); - renderToWriter(eb, options, w) catch return; + renderToWriter(eb, options, w, color.getTtyConf(ttyconf)) catch return; } -pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, w: *Writer) (Writer.Error || std.posix.UnexpectedError)!void { +pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, w: *Writer, ttyconf: Io.tty.Config) (Writer.Error || std.posix.UnexpectedError)!void { if (eb.extra.len == 0) return; for (eb.getMessages()) |err_msg| { - try renderErrorMessageToWriter(eb, options, err_msg, w, "error", .red, 0); + try renderErrorMessageToWriter(eb, options, err_msg, w, ttyconf, "error", .red, 0); } if (options.include_log_text) { @@ -190,11 +189,11 @@ fn renderErrorMessageToWriter( options: RenderOptions, err_msg_index: MessageIndex, w: *Writer, + ttyconf: Io.tty.Config, kind: []const u8, color: Io.tty.Color, indent: usize, ) (Writer.Error || std.posix.UnexpectedError)!void { - const ttyconf = options.ttyconf; const err_msg = eb.getErrorMessage(err_msg_index); if (err_msg.src_loc != .none) { const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc)); @@ -251,7 +250,7 @@ fn renderErrorMessageToWriter( try ttyconf.setColor(w, .reset); } for (eb.getNotes(err_msg_index)) |note| { - try renderErrorMessageToWriter(eb, options, note, w, "note", .cyan, indent); + try renderErrorMessageToWriter(eb, options, note, w, ttyconf, "note", .cyan, indent); } if (src.data.reference_trace_len > 0 and options.include_reference_trace) { try ttyconf.setColor(w, .reset); @@ -300,7 +299,7 @@ fn renderErrorMessageToWriter( } try ttyconf.setColor(w, .reset); for (eb.getNotes(err_msg_index)) |note| { - try renderErrorMessageToWriter(eb, options, note, w, "note", .cyan, indent + 4); + try renderErrorMessageToWriter(eb, options, note, w, ttyconf, "note", .cyan, indent + 4); } } } diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index d08f5b60ba..c3451f5238 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -6386,7 +6386,7 @@ var fixed_buffer_mem: [100 * 1024]u8 = undefined; fn testParse(source: [:0]const u8, allocator: mem.Allocator, anything_changed: *bool) ![]u8 { var buffer: [64]u8 = undefined; - const stderr = std.debug.lockStderrWriter(&buffer); + const stderr, _ = std.debug.lockStderrWriter(&buffer); defer std.debug.unlockStderrWriter(); var tree = try std.zig.Ast.parse(allocator, source, .zig); diff --git a/src/Air/print.zig b/src/Air/print.zig index 7f3758d47b..73cf2ed9b3 100644 --- a/src/Air/print.zig +++ b/src/Air/print.zig @@ -73,13 +73,13 @@ pub fn writeInst( } pub fn dump(air: Air, pt: Zcu.PerThread, liveness: ?Air.Liveness) void { - const stderr_bw = std.debug.lockStderrWriter(&.{}); + const stderr_bw, _ = std.debug.lockStderrWriter(&.{}); defer std.debug.unlockStderrWriter(); air.write(stderr_bw, pt, liveness); } pub fn dumpInst(air: Air, inst: Air.Inst.Index, pt: Zcu.PerThread, liveness: ?Air.Liveness) void { - const stderr_bw = std.debug.lockStderrWriter(&.{}); + const stderr_bw, _ = std.debug.lockStderrWriter(&.{}); defer std.debug.unlockStderrWriter(); air.writeInst(stderr_bw, inst, pt, liveness); } diff --git a/src/Compilation.zig b/src/Compilation.zig index 3670bc51b5..c72ef32fb5 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2093,7 +2093,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, if (options.verbose_llvm_cpu_features) { if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: { - const stderr_w = std.debug.lockStderrWriter(&.{}); + const stderr_w, _ = std.debug.lockStderrWriter(&.{}); defer std.debug.unlockStderrWriter(); stderr_w.print("compilation: {s}\n", .{options.root_name}) catch break :print; 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 { // However, we haven't reported any such error. // This is a compiler bug. print_ctx: { - var stderr_w = std.debug.lockStderrWriter(&.{}); + var stderr_w, _ = std.debug.lockStderrWriter(&.{}); defer std.debug.unlockStderrWriter(); stderr_w.writeAll("referenced transitive analysis errors, but none actually emitted\n") catch break :print_ctx; stderr_w.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)}) catch break :print_ctx; @@ -7752,7 +7752,7 @@ pub fn lockAndSetMiscFailure( pub fn dump_argv(argv: []const []const u8) void { var buffer: [64]u8 = undefined; - const stderr = std.debug.lockStderrWriter(&buffer); + const stderr, _ = std.debug.lockStderrWriter(&buffer); defer std.debug.unlockStderrWriter(); nosuspend { for (argv, 0..) |arg, i| { diff --git a/src/InternPool.zig b/src/InternPool.zig index a595fa502c..2a5436787c 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -11330,7 +11330,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { fn dumpAllFallible(ip: *const InternPool) anyerror!void { var buffer: [4096]u8 = undefined; - const stderr_bw = std.debug.lockStderrWriter(&buffer); + const stderr_bw, _ = std.debug.lockStderrWriter(&buffer); defer std.debug.unlockStderrWriter(); for (ip.locals, 0..) |*local, tid| { const items = local.shared.items.view(); @@ -11462,7 +11462,7 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator) } var buffer: [4096]u8 = undefined; - const stderr_bw = std.debug.lockStderrWriter(&buffer); + const stderr_bw, _ = std.debug.lockStderrWriter(&buffer); defer std.debug.unlockStderrWriter(); const SortContext = struct { diff --git a/src/Package/Fetch.zig b/src/Package/Fetch.zig index 46be6fa069..83d8aa7e5e 100644 --- a/src/Package/Fetch.zig +++ b/src/Package/Fetch.zig @@ -2043,7 +2043,7 @@ const UnpackResult = struct { defer errors.deinit(gpa); var aw: Io.Writer.Allocating = .init(gpa); defer aw.deinit(); - try errors.renderToWriter(.{ .ttyconf = .no_color }, &aw.writer); + try errors.renderToWriter(.{}, &aw.writer, .no_color); try std.testing.expectEqualStrings( \\error: unable to unpack \\ note: unable to create symlink from 'dir2/file2' to 'filename': SymlinkError @@ -2360,7 +2360,7 @@ const TestFetchBuilder = struct { } var aw: Io.Writer.Allocating = .init(std.testing.allocator); defer aw.deinit(); - try errors.renderToWriter(.{ .ttyconf = .no_color }, &aw.writer); + try errors.renderToWriter(.{}, &aw.writer, .no_color); try std.testing.expectEqualStrings(msg, aw.written()); } }; diff --git a/src/Sema.zig b/src/Sema.zig index 341cb1c855..4016041d82 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2631,7 +2631,7 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg Compilation.addModuleErrorMsg(zcu, &wip_errors, err_msg.*, false) catch @panic("out of memory"); std.debug.print("compile error during Sema:\n", .{}); var error_bundle = wip_errors.toOwnedBundle("") catch @panic("out of memory"); - error_bundle.renderToStdErr(.{ .ttyconf = .no_color }); + error_bundle.renderToStdErr(.{}, .auto); std.debug.panicExtra(@returnAddress(), "unexpected compile error occurred", .{}); } diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 474ccc710d..20aaa3d3c2 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -4473,7 +4473,7 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e defer if (liveness) |*l| l.deinit(gpa); if (build_options.enable_debug_extensions and comp.verbose_air) { - const stderr = std.debug.lockStderrWriter(&.{}); + const stderr, _ = std.debug.lockStderrWriter(&.{}); defer std.debug.unlockStderrWriter(); stderr.print("# Begin Function AIR: {f}:\n", .{fqn.fmt(ip)}) catch {}; air.write(stderr, pt, liveness); diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig index 43edde274c..8103a1a53d 100644 --- a/src/codegen/aarch64/Select.zig +++ b/src/codegen/aarch64/Select.zig @@ -11188,7 +11188,7 @@ fn initValueAdvanced( } pub fn dumpValues(isel: *Select, which: enum { only_referenced, all }) void { errdefer |err| @panic(@errorName(err)); - const stderr = std.debug.lockStderrWriter(&.{}); + const stderr, _ = std.debug.lockStderrWriter(&.{}); defer std.debug.unlockStderrWriter(); const zcu = isel.pt.zcu; diff --git a/src/crash_report.zig b/src/crash_report.zig index b051752c7a..d525d4b3b5 100644 --- a/src/crash_report.zig +++ b/src/crash_report.zig @@ -95,7 +95,7 @@ fn dumpCrashContext() Io.Writer.Error!void { // TODO: this does mean that a different thread could grab the stderr mutex between the context // and the actual panic printing, which would be quite confusing. - const stderr = std.debug.lockStderrWriter(&.{}); + const stderr, _ = std.debug.lockStderrWriter(&.{}); defer std.debug.unlockStderrWriter(); try stderr.writeAll("Compiler crash context:\n"); diff --git a/src/fmt.zig b/src/fmt.zig index 344a89d6ed..80925200d6 100644 --- a/src/fmt.zig +++ b/src/fmt.zig @@ -124,7 +124,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! try wip_errors.addZirErrorMessages(zir, tree, source_code, ""); var error_bundle = try wip_errors.toOwnedBundle(""); defer error_bundle.deinit(gpa); - error_bundle.renderToStdErr(color.renderOptions()); + error_bundle.renderToStdErr(.{}, color); process.exit(2); } } else { @@ -138,7 +138,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! try wip_errors.addZoirErrorMessages(zoir, tree, source_code, ""); var error_bundle = try wip_errors.toOwnedBundle(""); defer error_bundle.deinit(gpa); - error_bundle.renderToStdErr(color.renderOptions()); + error_bundle.renderToStdErr(.{}, color); process.exit(2); } } @@ -317,7 +317,7 @@ fn fmtPathFile( try wip_errors.addZirErrorMessages(zir, tree, source_code, file_path); var error_bundle = try wip_errors.toOwnedBundle(""); defer error_bundle.deinit(gpa); - error_bundle.renderToStdErr(fmt.color.renderOptions()); + error_bundle.renderToStdErr(.{}, fmt.color); fmt.any_error = true; } }, @@ -332,7 +332,7 @@ fn fmtPathFile( try wip_errors.addZoirErrorMessages(zoir, tree, source_code, file_path); var error_bundle = try wip_errors.toOwnedBundle(""); defer error_bundle.deinit(gpa); - error_bundle.renderToStdErr(fmt.color.renderOptions()); + error_bundle.renderToStdErr(.{}, fmt.color); fmt.any_error = true; } }, diff --git a/src/libs/mingw.zig b/src/libs/mingw.zig index 1773c321e1..e45e6c2856 100644 --- a/src/libs/mingw.zig +++ b/src/libs/mingw.zig @@ -312,7 +312,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { const include_dir = try comp.dirs.zig_lib.join(arena, &.{ "libc", "mingw", "def-include" }); if (comp.verbose_cc) print: { - var stderr = std.debug.lockStderrWriter(&.{}); + var stderr, _ = std.debug.lockStderrWriter(&.{}); defer std.debug.unlockStderrWriter(); nosuspend stderr.print("def file: {s}\n", .{def_file_path}) catch break :print; 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 { if (aro_comp.diagnostics.output.to_list.messages.items.len != 0) { var buffer: [64]u8 = undefined; - const w = std.debug.lockStderrWriter(&buffer); + const w, const ttyconf = std.debug.lockStderrWriter(&buffer); defer std.debug.unlockStderrWriter(); for (aro_comp.diagnostics.output.to_list.messages.items) |msg| { if (msg.kind == .@"fatal error" or msg.kind == .@"error") { - msg.write(w, .detect(std.fs.File.stderr()), true) catch {}; + msg.write(w, ttyconf, true) catch {}; return error.AroPreprocessorFailed; } } @@ -356,7 +356,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { error.OutOfMemory => |e| return e, error.ParseError => { var buffer: [64]u8 = undefined; - const w = std.debug.lockStderrWriter(&buffer); + const w, _ = std.debug.lockStderrWriter(&buffer); defer std.debug.unlockStderrWriter(); try w.writeAll("error: "); try def_diagnostics.writeMsg(w, input); diff --git a/src/libs/mingw/def.zig b/src/libs/mingw/def.zig index 98ea1a5396..24dc95c13c 100644 --- a/src/libs/mingw/def.zig +++ b/src/libs/mingw/def.zig @@ -1028,7 +1028,7 @@ fn testParse(machine_type: std.coff.IMAGE.FILE.MACHINE, source: [:0]const u8, ex const module = parse(std.testing.allocator, source, machine_type, .mingw, &diagnostics) catch |err| switch (err) { error.OutOfMemory => |e| return e, error.ParseError => { - const stderr = std.debug.lockStderrWriter(&.{}); + const stderr, _ = std.debug.lockStderrWriter(&.{}); defer std.debug.unlockStderrWriter(); try diagnostics.writeMsg(stderr, source); try stderr.writeByte('\n'); diff --git a/src/link.zig b/src/link.zig index 7cf8e5c1a6..5c4354411b 100644 --- a/src/link.zig +++ b/src/link.zig @@ -2215,7 +2215,7 @@ fn resolvePathInputLib( var error_bundle = try wip_errors.toOwnedBundle(""); defer error_bundle.deinit(gpa); - error_bundle.renderToStdErr(color.renderOptions()); + error_bundle.renderToStdErr(.{}, color); std.process.exit(1); } diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 32889684dc..9dbbccf70e 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -2335,7 +2335,7 @@ pub fn deleteExport(coff: *Coff, exported: Zcu.Exported, name: InternPool.NullTe } pub fn dump(coff: *Coff, tid: Zcu.PerThread.Id) void { - const w = std.debug.lockStderrWriter(&.{}); + const w, _ = std.debug.lockStderrWriter(&.{}); defer std.debug.unlockStderrWriter(); coff.printNode(tid, w, .root, 0) catch {}; } diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig index 93fa490907..6f1f9d6f0e 100644 --- a/src/link/Elf2.zig +++ b/src/link/Elf2.zig @@ -1965,7 +1965,7 @@ pub fn deleteExport(elf: *Elf, exported: Zcu.Exported, name: InternPool.NullTerm } pub fn dump(elf: *Elf, tid: Zcu.PerThread.Id) void { - const w = std.debug.lockStderrWriter(&.{}); + const w, _ = std.debug.lockStderrWriter(&.{}); defer std.debug.unlockStderrWriter(); elf.printNode(tid, w, .root, 0) catch {}; } diff --git a/src/main.zig b/src/main.zig index 03d42ba898..d134dd9bd2 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4520,7 +4520,7 @@ fn updateModule(comp: *Compilation, color: Color, prog_node: std.Progress.Node) defer errors.deinit(comp.gpa); if (errors.errorMessageCount() > 0) { - errors.renderToStdErr(color.renderOptions()); + errors.renderToStdErr(.{}, color); return error.CompileErrorsReported; } } @@ -4573,7 +4573,7 @@ fn cmdTranslateC( return; } else { const color: Color = .auto; - result.errors.renderToStdErr(color.renderOptions()); + result.errors.renderToStdErr(.{}, color); process.exit(1); } } @@ -5199,7 +5199,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) if (fetch.error_bundle.root_list.items.len > 0) { var errors = try fetch.error_bundle.toOwnedBundle(""); - errors.renderToStdErr(color.renderOptions()); + errors.renderToStdErr(.{}, color); process.exit(1); } @@ -6135,7 +6135,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void { try wip_errors.init(arena); try wip_errors.addZirErrorMessages(zir, tree, source, display_path); var error_bundle = try wip_errors.toOwnedBundle(""); - error_bundle.renderToStdErr(color.renderOptions()); + error_bundle.renderToStdErr(.{}, color); if (zir.loweringFailed()) { process.exit(1); } @@ -6206,7 +6206,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void { try wip_errors.init(arena); try wip_errors.addZoirErrorMessages(zoir, tree, source, display_path); var error_bundle = try wip_errors.toOwnedBundle(""); - error_bundle.renderToStdErr(color.renderOptions()); + error_bundle.renderToStdErr(.{}, color); process.exit(1); } @@ -6479,7 +6479,7 @@ fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8) !void { try wip_errors.init(arena); try wip_errors.addZirErrorMessages(old_zir, old_tree, old_source, old_source_path); var error_bundle = try wip_errors.toOwnedBundle(""); - error_bundle.renderToStdErr(color.renderOptions()); + error_bundle.renderToStdErr(.{}, color); process.exit(1); } @@ -6491,7 +6491,7 @@ fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8) !void { try wip_errors.init(arena); try wip_errors.addZirErrorMessages(new_zir, new_tree, new_source, new_source_path); var error_bundle = try wip_errors.toOwnedBundle(""); - error_bundle.renderToStdErr(color.renderOptions()); + error_bundle.renderToStdErr(.{}, color); process.exit(1); } @@ -6948,7 +6948,7 @@ fn cmdFetch( if (fetch.error_bundle.root_list.items.len > 0) { var errors = try fetch.error_bundle.toOwnedBundle(""); - errors.renderToStdErr(color.renderOptions()); + errors.renderToStdErr(.{}, color); process.exit(1); } @@ -7304,7 +7304,7 @@ fn loadManifest( var error_bundle = try wip_errors.toOwnedBundle(""); defer error_bundle.deinit(gpa); - error_bundle.renderToStdErr(options.color.renderOptions()); + error_bundle.renderToStdErr(.{}, options.color); process.exit(2); } diff --git a/tools/gen_spirv_spec.zig b/tools/gen_spirv_spec.zig index 702866824c..c211d1022e 100644 --- a/tools/gen_spirv_spec.zig +++ b/tools/gen_spirv_spec.zig @@ -89,10 +89,9 @@ pub fn main() !void { const output = allocating.written()[0 .. allocating.written().len - 1 :0]; var tree = try std.zig.Ast.parse(allocator, output, .zig); - var color: std.zig.Color = .on; if (tree.errors.len != 0) { - try std.zig.printAstErrorsToStderr(allocator, tree, "", color); + try std.zig.printAstErrorsToStderr(allocator, tree, "", .auto); return; } @@ -104,7 +103,7 @@ pub fn main() !void { try wip_errors.addZirErrorMessages(zir, tree, output, ""); var error_bundle = try wip_errors.toOwnedBundle(""); defer error_bundle.deinit(allocator); - error_bundle.renderToStdErr(color.renderOptions()); + error_bundle.renderToStdErr(.{}, .auto); } const formatted_output = try tree.renderAlloc(allocator); @@ -931,7 +930,7 @@ fn parseHexInt(text: []const u8) !u31 { } fn usageAndExit(arg0: []const u8, code: u8) noreturn { - const stderr = std.debug.lockStderrWriter(&.{}); + const stderr, _ = std.debug.lockStderrWriter(&.{}); stderr.print( \\Usage: {s} \\ diff --git a/tools/generate_linux_syscalls.zig b/tools/generate_linux_syscalls.zig index 2705618a7d..e009715e2f 100644 --- a/tools/generate_linux_syscalls.zig +++ b/tools/generate_linux_syscalls.zig @@ -177,7 +177,9 @@ pub fn main() !void { const args = try std.process.argsAlloc(gpa); if (args.len < 2 or mem.eql(u8, args[1], "--help")) { - usage(std.debug.lockStderrWriter(&.{}), args[0]) catch std.process.exit(2); + const w, _ = std.debug.lockStderrWriter(&.{}); + defer std.debug.unlockStderrWriter(); + usage(w, args[0]) catch std.process.exit(2); std.process.exit(1); } const linux_path = args[1]; diff --git a/tools/incr-check.zig b/tools/incr-check.zig index 22031e147a..dffd3ccb34 100644 --- a/tools/incr-check.zig +++ b/tools/incr-check.zig @@ -340,8 +340,7 @@ const Eval = struct { .unknown => return, .compile_errors => |ce| ce, .stdout, .exit_code => { - const color: std.zig.Color = .auto; - error_bundle.renderToStdErr(color.renderOptions()); + error_bundle.renderToStdErr(.{}, .auto); eval.fatal("update '{s}': unexpected compile errors", .{update.name}); }, }; @@ -350,8 +349,7 @@ const Eval = struct { for (error_bundle.getMessages()) |err_idx| { if (expected_idx == expected.errors.len) { - const color: std.zig.Color = .auto; - error_bundle.renderToStdErr(color.renderOptions()); + error_bundle.renderToStdErr(.{}, .auto); eval.fatal("update '{s}': more errors than expected", .{update.name}); } try eval.checkOneError(update, error_bundle, expected.errors[expected_idx], false, err_idx); @@ -359,8 +357,7 @@ const Eval = struct { for (error_bundle.getNotes(err_idx)) |note_idx| { if (expected_idx == expected.errors.len) { - const color: std.zig.Color = .auto; - error_bundle.renderToStdErr(color.renderOptions()); + error_bundle.renderToStdErr(.{}, .auto); eval.fatal("update '{s}': more error notes than expected", .{update.name}); } try eval.checkOneError(update, error_bundle, expected.errors[expected_idx], true, note_idx); @@ -369,8 +366,7 @@ const Eval = struct { } if (!std.mem.eql(u8, error_bundle.getCompileLogOutput(), expected.compile_log_output)) { - const color: std.zig.Color = .auto; - error_bundle.renderToStdErr(color.renderOptions()); + error_bundle.renderToStdErr(.{}, .auto); eval.fatal("update '{s}': unexpected compile log output", .{update.name}); } } @@ -404,8 +400,7 @@ const Eval = struct { expected.column != src.column + 1 or !std.mem.eql(u8, expected.msg, msg)) { - const color: std.zig.Color = .auto; - eb.renderToStdErr(color.renderOptions()); + eb.renderToStdErr(.{}, .auto); eval.fatal("update '{s}': compile error did not match expected error", .{update.name}); } } diff --git a/tools/update_clang_options.zig b/tools/update_clang_options.zig index 9b054478a2..c8b941cbfa 100644 --- a/tools/update_clang_options.zig +++ b/tools/update_clang_options.zig @@ -961,7 +961,9 @@ fn objectLessThan(context: void, a: *json.ObjectMap, b: *json.ObjectMap) bool { } fn printUsageAndExit(arg0: []const u8) noreturn { - printUsage(std.debug.lockStderrWriter(&.{}), arg0) catch std.process.exit(2); + const w, _ = std.debug.lockStderrWriter(&.{}); + defer std.debug.unlockStderrWriter(); + printUsage(w, arg0) catch std.process.exit(2); std.process.exit(1); } diff --git a/tools/update_cpu_features.zig b/tools/update_cpu_features.zig index 786c78544d..eeaa2bb393 100644 --- a/tools/update_cpu_features.zig +++ b/tools/update_cpu_features.zig @@ -2167,7 +2167,7 @@ fn processOneTarget(job: Job) void { } fn usageAndExit(arg0: []const u8, code: u8) noreturn { - const stderr = std.debug.lockStderrWriter(&.{}); + const stderr, _ = std.debug.lockStderrWriter(&.{}); stderr.print( \\Usage: {s} /path/to/llvm-tblgen /path/git/llvm-project /path/git/zig [zig_name filter] \\ diff --git a/tools/update_crc_catalog.zig b/tools/update_crc_catalog.zig index a973a1b75a..4c8614e02f 100644 --- a/tools/update_crc_catalog.zig +++ b/tools/update_crc_catalog.zig @@ -190,7 +190,9 @@ pub fn main() anyerror!void { } fn printUsageAndExit(arg0: []const u8) noreturn { - printUsage(std.debug.lockStderrWriter(&.{}), arg0) catch std.process.exit(2); + const w, _ = std.debug.lockStderrWriter(&.{}); + defer std.debug.unlockStderrWriter(); + printUsage(w, arg0) catch std.process.exit(2); std.process.exit(1); }