authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-08 21:00:04-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-23 22:15:08-08:00
logbee8005fe6817ade9191de0493888b14cdbcac31
tree6001bd45ab1118e92a77fe6ebfbf6b332d371a2b
parent4a53e5b0b4131c6b8e18bb551e8215e425f8ac71

std.heap.DebugAllocator: never detect TTY config

instead, allow the user to set it as a field. this fixes a bug where leak printing and error printing would run tty config detection for stderr, and then emit a log, which is not necessary going to print to stderr. however, the nice defaults are gone; the user must explicitly assign the tty_config field during initialization or else the logging will not have color. related: https://github.com/ziglang/zig/issues/24510

25 files changed, 113 insertions(+), 86 deletions(-)

lib/compiler/build_runner.zig+1-1
...@@ -435,7 +435,7 @@ pub fn main() !void {...@@ -435,7 +435,7 @@ pub fn main() !void {
435 if (builtin.single_threaded) fatal("'--webui' is not yet supported on single-threaded hosts", .{});435 if (builtin.single_threaded) fatal("'--webui' is not yet supported on single-threaded hosts", .{});
436 }436 }
437437
438 const ttyconf = color.detectTtyConf();438 const ttyconf = color.detectTtyConf(io);
439439
440 const main_progress_node = std.Progress.start(.{440 const main_progress_node = std.Progress.start(.{
441 .disable_printing = (color == .off),441 .disable_printing = (color == .off),
lib/std/Build/Fuzz.zig+10-9
...@@ -360,12 +360,13 @@ fn coverageRunCancelable(fuzz: *Fuzz) Io.Cancelable!void {...@@ -360,12 +360,13 @@ fn coverageRunCancelable(fuzz: *Fuzz) Io.Cancelable!void {
360fn prepareTables(fuzz: *Fuzz, run_step: *Step.Run, coverage_id: u64) error{ OutOfMemory, AlreadyReported, Canceled }!void {360fn prepareTables(fuzz: *Fuzz, run_step: *Step.Run, coverage_id: u64) error{ OutOfMemory, AlreadyReported, Canceled }!void {
361 assert(fuzz.mode == .forever);361 assert(fuzz.mode == .forever);
362 const ws = fuzz.mode.forever.ws;362 const ws = fuzz.mode.forever.ws;
363 const gpa = fuzz.gpa;
363 const io = fuzz.io;364 const io = fuzz.io;
364365
365 try fuzz.coverage_mutex.lock(io);366 try fuzz.coverage_mutex.lock(io);
366 defer fuzz.coverage_mutex.unlock(io);367 defer fuzz.coverage_mutex.unlock(io);
367368
368 const gop = try fuzz.coverage_files.getOrPut(fuzz.gpa, coverage_id);369 const gop = try fuzz.coverage_files.getOrPut(gpa, coverage_id);
369 if (gop.found_existing) {370 if (gop.found_existing) {
370 // We are fuzzing the same executable with multiple threads.371 // We are fuzzing the same executable with multiple threads.
371 // Perhaps the same unit test; perhaps a different one. In any372 // Perhaps the same unit test; perhaps a different one. In any
...@@ -383,12 +384,12 @@ fn prepareTables(fuzz: *Fuzz, run_step: *Step.Run, coverage_id: u64) error{ OutO...@@ -383,12 +384,12 @@ fn prepareTables(fuzz: *Fuzz, run_step: *Step.Run, coverage_id: u64) error{ OutO
383 .entry_points = .{},384 .entry_points = .{},
384 .start_timestamp = ws.now(),385 .start_timestamp = ws.now(),
385 };386 };
386 errdefer gop.value_ptr.coverage.deinit(fuzz.gpa);387 errdefer gop.value_ptr.coverage.deinit(gpa);
387388
388 const rebuilt_exe_path = run_step.rebuilt_executable.?;389 const rebuilt_exe_path = run_step.rebuilt_executable.?;
389 const target = run_step.producer.?.rootModuleTarget();390 const target = run_step.producer.?.rootModuleTarget();
390 var debug_info = std.debug.Info.load(391 var debug_info = std.debug.Info.load(
391 fuzz.gpa,392 gpa,
392 io,393 io,
393 rebuilt_exe_path,394 rebuilt_exe_path,
394 &gop.value_ptr.coverage,395 &gop.value_ptr.coverage,
...@@ -400,7 +401,7 @@ fn prepareTables(fuzz: *Fuzz, run_step: *Step.Run, coverage_id: u64) error{ OutO...@@ -400,7 +401,7 @@ fn prepareTables(fuzz: *Fuzz, run_step: *Step.Run, coverage_id: u64) error{ OutO
400 });401 });
401 return error.AlreadyReported;402 return error.AlreadyReported;
402 };403 };
403 defer debug_info.deinit(fuzz.gpa);404 defer debug_info.deinit(gpa);
404405
405 const coverage_file_path: Build.Cache.Path = .{406 const coverage_file_path: Build.Cache.Path = .{
406 .root_dir = run_step.step.owner.cache_root,407 .root_dir = run_step.step.owner.cache_root,
...@@ -434,14 +435,14 @@ fn prepareTables(fuzz: *Fuzz, run_step: *Step.Run, coverage_id: u64) error{ OutO...@@ -434,14 +435,14 @@ fn prepareTables(fuzz: *Fuzz, run_step: *Step.Run, coverage_id: u64) error{ OutO
434435
435 const header: *const abi.SeenPcsHeader = @ptrCast(mapped_memory[0..@sizeOf(abi.SeenPcsHeader)]);436 const header: *const abi.SeenPcsHeader = @ptrCast(mapped_memory[0..@sizeOf(abi.SeenPcsHeader)]);
436 const pcs = header.pcAddrs();437 const pcs = header.pcAddrs();
437 const source_locations = try fuzz.gpa.alloc(Coverage.SourceLocation, pcs.len);438 const source_locations = try gpa.alloc(Coverage.SourceLocation, pcs.len);
438 errdefer fuzz.gpa.free(source_locations);439 errdefer gpa.free(source_locations);
439440
440 // Unfortunately the PCs array that LLVM gives us from the 8-bit PC441 // Unfortunately the PCs array that LLVM gives us from the 8-bit PC
441 // counters feature is not sorted.442 // counters feature is not sorted.
442 var sorted_pcs: std.MultiArrayList(struct { pc: u64, index: u32, sl: Coverage.SourceLocation }) = .{};443 var sorted_pcs: std.MultiArrayList(struct { pc: u64, index: u32, sl: Coverage.SourceLocation }) = .{};
443 defer sorted_pcs.deinit(fuzz.gpa);444 defer sorted_pcs.deinit(gpa);
444 try sorted_pcs.resize(fuzz.gpa, pcs.len);445 try sorted_pcs.resize(gpa, pcs.len);
445 @memcpy(sorted_pcs.items(.pc), pcs);446 @memcpy(sorted_pcs.items(.pc), pcs);
446 for (sorted_pcs.items(.index), 0..) |*v, i| v.* = @intCast(i);447 for (sorted_pcs.items(.index), 0..) |*v, i| v.* = @intCast(i);
447 sorted_pcs.sortUnstable(struct {448 sorted_pcs.sortUnstable(struct {
...@@ -452,7 +453,7 @@ fn prepareTables(fuzz: *Fuzz, run_step: *Step.Run, coverage_id: u64) error{ OutO...@@ -452,7 +453,7 @@ fn prepareTables(fuzz: *Fuzz, run_step: *Step.Run, coverage_id: u64) error{ OutO
452 }453 }
453 }{ .addrs = sorted_pcs.items(.pc) });454 }{ .addrs = sorted_pcs.items(.pc) });
454455
455 debug_info.resolveAddresses(fuzz.gpa, sorted_pcs.items(.pc), sorted_pcs.items(.sl)) catch |err| {456 debug_info.resolveAddresses(gpa, io, sorted_pcs.items(.pc), sorted_pcs.items(.sl)) catch |err| {
456 log.err("failed to resolve addresses to source locations: {t}", .{err});457 log.err("failed to resolve addresses to source locations: {t}", .{err});
457 return error.AlreadyReported;458 return error.AlreadyReported;
458 };459 };
lib/std/Build/Step/InstallArtifact.zig+1-1
...@@ -172,7 +172,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -172,7 +172,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
172 defer src_dir.close(io);172 defer src_dir.close(io);
173173
174 var it = try src_dir.walk(b.allocator);174 var it = try src_dir.walk(b.allocator);
175 next_entry: while (try it.next()) |entry| {175 next_entry: while (try it.next(io)) |entry| {
176 for (dir.options.exclude_extensions) |ext| {176 for (dir.options.exclude_extensions) |ext| {
177 if (std.mem.endsWith(u8, entry.path, ext)) continue :next_entry;177 if (std.mem.endsWith(u8, entry.path, ext)) continue :next_entry;
178 }178 }
lib/std/Build/Step/WriteFile.zig+1-1
...@@ -309,7 +309,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -309,7 +309,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
309309
310 var it = try already_open_dir.walk(gpa);310 var it = try already_open_dir.walk(gpa);
311 defer it.deinit();311 defer it.deinit();
312 while (try it.next()) |entry| {312 while (try it.next(io)) |entry| {
313 if (!dir.options.pathIncluded(entry.path)) continue;313 if (!dir.options.pathIncluded(entry.path)) continue;
314314
315 const src_entry_path = try src_dir_path.join(arena, entry.path);315 const src_entry_path = try src_dir_path.join(arena, entry.path);
lib/std/Io/Dir.zig+4-4
...@@ -574,7 +574,7 @@ pub fn updateFile(...@@ -574,7 +574,7 @@ pub fn updateFile(
574 error.WriteFailed => return atomic_file.file_writer.err.?,574 error.WriteFailed => return atomic_file.file_writer.err.?,
575 };575 };
576 try atomic_file.flush();576 try atomic_file.flush();
577 try atomic_file.file_writer.file.updateTimes(src_stat.atime, src_stat.mtime);577 try atomic_file.file_writer.file.setTimestamps(io, src_stat.atime, src_stat.mtime);
578 try atomic_file.renameIntoPlace();578 try atomic_file.renameIntoPlace();
579 return .stale;579 return .stale;
580}580}
...@@ -1238,7 +1238,7 @@ pub fn deleteTree(dir: Dir, io: Io, sub_path: []const u8) DeleteTreeError!void {...@@ -1238,7 +1238,7 @@ pub fn deleteTree(dir: Dir, io: Io, sub_path: []const u8) DeleteTreeError!void {
12381238
1239 process_stack: while (stack.items.len != 0) {1239 process_stack: while (stack.items.len != 0) {
1240 var top = &stack.items[stack.items.len - 1];1240 var top = &stack.items[stack.items.len - 1];
1241 while (try top.iter.next()) |entry| {1241 while (try top.iter.next(io)) |entry| {
1242 var treat_as_dir = entry.kind == .directory;1242 var treat_as_dir = entry.kind == .directory;
1243 handle_entry: while (true) {1243 handle_entry: while (true) {
1244 if (treat_as_dir) {1244 if (treat_as_dir) {
...@@ -1695,9 +1695,9 @@ pub fn atomicFile(parent: Dir, io: Io, dest_path: []const u8, options: AtomicFil...@@ -1695,9 +1695,9 @@ pub fn atomicFile(parent: Dir, io: Io, dest_path: []const u8, options: AtomicFil
1695 else1695 else
1696 try parent.openDir(io, dirname, .{});1696 try parent.openDir(io, dirname, .{});
16971697
1698 return .init(path.basename(dest_path), options.permissions, dir, true, options.write_buffer);1698 return .init(io, path.basename(dest_path), options.permissions, dir, true, options.write_buffer);
1699 } else {1699 } else {
1700 return .init(dest_path, options.permissions, parent, false, options.write_buffer);1700 return .init(io, dest_path, options.permissions, parent, false, options.write_buffer);
1701 }1701 }
1702}1702}
17031703
lib/std/Io/File.zig+1-1
...@@ -460,7 +460,7 @@ pub fn setTimestamps(...@@ -460,7 +460,7 @@ pub fn setTimestamps(
460 last_accessed: Io.Timestamp,460 last_accessed: Io.Timestamp,
461 last_modified: Io.Timestamp,461 last_modified: Io.Timestamp,
462) SetTimestampsError!void {462) SetTimestampsError!void {
463 return io.vtable.fileUpdateTimes(io.userdata, file, last_accessed, last_modified);463 return io.vtable.fileSetTimestamps(io.userdata, file, last_accessed, last_modified);
464}464}
465465
466/// Sets the accessed and modification timestamps of `file` to the current wall466/// Sets the accessed and modification timestamps of `file` to the current wall
lib/std/Io/File/Atomic.zig+1-1
...@@ -66,7 +66,7 @@ pub fn deinit(af: *Atomic) void {...@@ -66,7 +66,7 @@ pub fn deinit(af: *Atomic) void {
66 af.* = undefined;66 af.* = undefined;
67}67}
6868
69pub const FlushError = File.WriteError;69pub const FlushError = File.Writer.Error;
7070
71pub fn flush(af: *Atomic) FlushError!void {71pub fn flush(af: *Atomic) FlushError!void {
72 af.file_writer.interface.flush() catch |err| switch (err) {72 af.file_writer.interface.flush() catch |err| switch (err) {
lib/std/Io/File/Writer.zig+5-4
...@@ -158,7 +158,7 @@ pub fn sendFile(io_w: *Io.Writer, file_reader: *Io.File.Reader, limit: Io.Limit)...@@ -158,7 +158,7 @@ pub fn sendFile(io_w: *Io.Writer, file_reader: *Io.File.Reader, limit: Io.Limit)
158fn sendFilePositional(w: *Writer, file_reader: *Io.File.Reader, limit: Io.Limit) Io.Writer.FileError!usize {158fn sendFilePositional(w: *Writer, file_reader: *Io.File.Reader, limit: Io.Limit) Io.Writer.FileError!usize {
159 const io = w.io;159 const io = w.io;
160 const header = w.interface.buffered();160 const header = w.interface.buffered();
161 const n = io.vtable.fileSendFilePositional(io.userdata, w.file, header, file_reader, limit, w.pos) catch |err| switch (err) {161 const n = io.vtable.fileWriteFilePositional(io.userdata, w.file, header, file_reader, limit, w.pos) catch |err| switch (err) {
162 error.Unseekable => {162 error.Unseekable => {
163 w.mode = w.mode.toStreaming();163 w.mode = w.mode.toStreaming();
164 const pos = w.pos;164 const pos = w.pos;
...@@ -187,7 +187,7 @@ fn sendFilePositional(w: *Writer, file_reader: *Io.File.Reader, limit: Io.Limit)...@@ -187,7 +187,7 @@ fn sendFilePositional(w: *Writer, file_reader: *Io.File.Reader, limit: Io.Limit)
187fn sendFileStreaming(w: *Writer, file_reader: *Io.File.Reader, limit: Io.Limit) Io.Writer.FileError!usize {187fn sendFileStreaming(w: *Writer, file_reader: *Io.File.Reader, limit: Io.Limit) Io.Writer.FileError!usize {
188 const io = w.io;188 const io = w.io;
189 const header = w.interface.buffered();189 const header = w.interface.buffered();
190 const n = io.vtable.fileSendFileStreaming(io.userdata, w.file, header, file_reader, limit) catch |err| switch (err) {190 const n = io.vtable.fileWriteFileStreaming(io.userdata, w.file, header, file_reader, limit) catch |err| switch (err) {
191 error.Canceled => {191 error.Canceled => {
192 w.err = error.Canceled;192 w.err = error.Canceled;
193 return error.WriteFailed;193 return error.WriteFailed;
...@@ -226,7 +226,7 @@ pub fn seekToUnbuffered(w: *Writer, offset: u64) SeekError!void {...@@ -226,7 +226,7 @@ pub fn seekToUnbuffered(w: *Writer, offset: u64) SeekError!void {
226 }226 }
227}227}
228228
229pub const EndError = File.SetEndPosError || Io.Writer.Error;229pub const EndError = File.SetLengthError || Io.Writer.Error;
230230
231/// Flushes any buffered data and sets the end position of the file.231/// Flushes any buffered data and sets the end position of the file.
232///232///
...@@ -236,11 +236,12 @@ pub const EndError = File.SetEndPosError || Io.Writer.Error;...@@ -236,11 +236,12 @@ pub const EndError = File.SetEndPosError || Io.Writer.Error;
236/// Flush failure is handled by setting `err` so that it can be handled236/// Flush failure is handled by setting `err` so that it can be handled
237/// along with other write failures.237/// along with other write failures.
238pub fn end(w: *Writer) EndError!void {238pub fn end(w: *Writer) EndError!void {
239 const io = w.io;
239 try w.interface.flush();240 try w.interface.flush();
240 switch (w.mode) {241 switch (w.mode) {
241 .positional,242 .positional,
242 .positional_reading,243 .positional_reading,
243 => w.file.setLength(w.pos) catch |err| switch (err) {244 => w.file.setLength(io, w.pos) catch |err| switch (err) {
244 error.NonResizable => return,245 error.NonResizable => return,
245 else => |e| return e,246 else => |e| return e,
246 },247 },
lib/std/Io/Threaded.zig+16-16
...@@ -4,8 +4,6 @@ const builtin = @import("builtin");...@@ -4,8 +4,6 @@ const builtin = @import("builtin");
4const native_os = builtin.os.tag;4const native_os = builtin.os.tag;
5const is_windows = native_os == .windows;5const is_windows = native_os == .windows;
6const is_darwin = native_os.isDarwin();6const is_darwin = native_os.isDarwin();
7const windows = std.os.windows;
8const ws2_32 = std.os.windows.ws2_32;
9const is_debug = builtin.mode == .Debug;7const is_debug = builtin.mode == .Debug;
108
11const std = @import("../std.zig");9const std = @import("../std.zig");
...@@ -19,6 +17,8 @@ const Allocator = std.mem.Allocator;...@@ -19,6 +17,8 @@ const Allocator = std.mem.Allocator;
19const Alignment = std.mem.Alignment;17const Alignment = std.mem.Alignment;
20const assert = std.debug.assert;18const assert = std.debug.assert;
21const posix = std.posix;19const posix = std.posix;
20const windows = std.os.windows;
21const ws2_32 = std.os.windows.ws2_32;
2222
23/// Thread-safe.23/// Thread-safe.
24allocator: Allocator,24allocator: Allocator,
...@@ -1452,7 +1452,7 @@ const dirMake = switch (native_os) {...@@ -1452,7 +1452,7 @@ const dirMake = switch (native_os) {
1452 else => dirMakePosix,1452 else => dirMakePosix,
1453};1453};
14541454
1455fn dirMakePosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, mode: Dir.Mode) Dir.MakeError!void {1455fn dirMakePosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, permissions: Dir.Permissions) Dir.MakeError!void {
1456 const t: *Threaded = @ptrCast(@alignCast(userdata));1456 const t: *Threaded = @ptrCast(@alignCast(userdata));
1457 const current_thread = Thread.getCurrent(t);1457 const current_thread = Thread.getCurrent(t);
14581458
...@@ -1461,7 +1461,7 @@ fn dirMakePosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, mode: Dir...@@ -1461,7 +1461,7 @@ fn dirMakePosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, mode: Dir
14611461
1462 try current_thread.beginSyscall();1462 try current_thread.beginSyscall();
1463 while (true) {1463 while (true) {
1464 switch (posix.errno(posix.system.mkdirat(dir.handle, sub_path_posix, mode))) {1464 switch (posix.errno(posix.system.mkdirat(dir.handle, sub_path_posix, permissions.toMode()))) {
1465 .SUCCESS => {1465 .SUCCESS => {
1466 current_thread.endSyscall();1466 current_thread.endSyscall();
1467 return;1467 return;
...@@ -1498,8 +1498,8 @@ fn dirMakePosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, mode: Dir...@@ -1498,8 +1498,8 @@ fn dirMakePosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, mode: Dir
1498 }1498 }
1499}1499}
15001500
1501fn dirMakeWasi(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, mode: Dir.Mode) Dir.MakeError!void {1501fn dirMakeWasi(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, permissions: Dir.Permissions) Dir.MakeError!void {
1502 if (builtin.link_libc) return dirMakePosix(userdata, dir, sub_path, mode);1502 if (builtin.link_libc) return dirMakePosix(userdata, dir, sub_path, permissions);
1503 const t: *Threaded = @ptrCast(@alignCast(userdata));1503 const t: *Threaded = @ptrCast(@alignCast(userdata));
1504 const current_thread = Thread.getCurrent(t);1504 const current_thread = Thread.getCurrent(t);
1505 try current_thread.beginSyscall();1505 try current_thread.beginSyscall();
...@@ -1540,13 +1540,13 @@ fn dirMakeWasi(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, mode: Dir....@@ -1540,13 +1540,13 @@ fn dirMakeWasi(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, mode: Dir.
1540 }1540 }
1541}1541}
15421542
1543fn dirMakeWindows(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, mode: Dir.Mode) Dir.MakeError!void {1543fn dirMakeWindows(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, permissions: Dir.Permissions) Dir.MakeError!void {
1544 const t: *Threaded = @ptrCast(@alignCast(userdata));1544 const t: *Threaded = @ptrCast(@alignCast(userdata));
1545 const current_thread = Thread.getCurrent(t);1545 const current_thread = Thread.getCurrent(t);
1546 try current_thread.checkCancel();1546 try current_thread.checkCancel();
15471547
1548 const sub_path_w = try windows.sliceToPrefixedFileW(dir.handle, sub_path);1548 const sub_path_w = try windows.sliceToPrefixedFileW(dir.handle, sub_path);
1549 _ = mode;1549 _ = permissions; // TODO use this value
1550 const sub_dir_handle = windows.OpenFile(sub_path_w.span(), .{1550 const sub_dir_handle = windows.OpenFile(sub_path_w.span(), .{
1551 .dir = dir.handle,1551 .dir = dir.handle,
1552 .access_mask = .{1552 .access_mask = .{
...@@ -1570,7 +1570,7 @@ fn dirMakePath(...@@ -1570,7 +1570,7 @@ fn dirMakePath(
1570 userdata: ?*anyopaque,1570 userdata: ?*anyopaque,
1571 dir: Dir,1571 dir: Dir,
1572 sub_path: []const u8,1572 sub_path: []const u8,
1573 mode: Dir.Mode,1573 permissions: Dir.Permissions,
1574) Dir.MakePathError!Dir.MakePathStatus {1574) Dir.MakePathError!Dir.MakePathStatus {
1575 const t: *Threaded = @ptrCast(@alignCast(userdata));1575 const t: *Threaded = @ptrCast(@alignCast(userdata));
15761576
...@@ -1578,7 +1578,7 @@ fn dirMakePath(...@@ -1578,7 +1578,7 @@ fn dirMakePath(
1578 var status: Dir.MakePathStatus = .existed;1578 var status: Dir.MakePathStatus = .existed;
1579 var component = it.last() orelse return error.BadPathName;1579 var component = it.last() orelse return error.BadPathName;
1580 while (true) {1580 while (true) {
1581 if (dirMake(t, dir, component.path, mode)) |_| {1581 if (dirMake(t, dir, component.path, permissions)) |_| {
1582 status = .created;1582 status = .created;
1583 } else |err| switch (err) {1583 } else |err| switch (err) {
1584 error.PathAlreadyExists => {1584 error.PathAlreadyExists => {
...@@ -4945,7 +4945,7 @@ fn dirSetTimestamps(...@@ -4945,7 +4945,7 @@ fn dirSetTimestamps(
4945 sub_path: []const u8,4945 sub_path: []const u8,
4946 last_accessed: Io.Timestamp,4946 last_accessed: Io.Timestamp,
4947 last_modified: Io.Timestamp,4947 last_modified: Io.Timestamp,
4948 options: File.SetTimestampsOptions,4948 options: Dir.SetTimestampsOptions,
4949) File.SetTimestampsError!void {4949) File.SetTimestampsError!void {
4950 const t: *Threaded = @ptrCast(@alignCast(userdata));4950 const t: *Threaded = @ptrCast(@alignCast(userdata));
4951 const current_thread = Thread.getCurrent(t);4951 const current_thread = Thread.getCurrent(t);
...@@ -4997,7 +4997,7 @@ fn dirSetTimestampsNow(...@@ -4997,7 +4997,7 @@ fn dirSetTimestampsNow(
4997 userdata: ?*anyopaque,4997 userdata: ?*anyopaque,
4998 dir: Dir,4998 dir: Dir,
4999 sub_path: []const u8,4999 sub_path: []const u8,
5000 options: File.SetTimestampsOptions,5000 options: Dir.SetTimestampsOptions,
5001) File.SetTimestampsError!void {5001) File.SetTimestampsError!void {
5002 const t: *Threaded = @ptrCast(@alignCast(userdata));5002 const t: *Threaded = @ptrCast(@alignCast(userdata));
5003 const current_thread = Thread.getCurrent(t);5003 const current_thread = Thread.getCurrent(t);
...@@ -6271,7 +6271,7 @@ fn fileWriteStreaming(...@@ -6271,7 +6271,7 @@ fn fileWriteStreaming(
6271 header: []const u8,6271 header: []const u8,
6272 data: []const []const u8,6272 data: []const []const u8,
6273 splat: usize,6273 splat: usize,
6274) File.WriteStreamingError!usize {6274) File.Writer.Error!usize {
6275 const t: *Threaded = @ptrCast(@alignCast(userdata));6275 const t: *Threaded = @ptrCast(@alignCast(userdata));
6276 const current_thread = Thread.getCurrent(t);6276 const current_thread = Thread.getCurrent(t);
62776277
...@@ -9690,7 +9690,7 @@ fn statFromLinux(stx: *const std.os.linux.Statx) File.Stat {...@@ -9690,7 +9690,7 @@ fn statFromLinux(stx: *const std.os.linux.Statx) File.Stat {
9690 return .{9690 return .{
9691 .inode = stx.ino,9691 .inode = stx.ino,
9692 .size = stx.size,9692 .size = stx.size,
9693 .mode = stx.mode,9693 .permissions = .fromMode(stx.mode),
9694 .kind = switch (stx.mode & std.os.linux.S.IFMT) {9694 .kind = switch (stx.mode & std.os.linux.S.IFMT) {
9695 std.os.linux.S.IFDIR => .directory,9695 std.os.linux.S.IFDIR => .directory,
9696 std.os.linux.S.IFCHR => .character_device,9696 std.os.linux.S.IFCHR => .character_device,
...@@ -9714,7 +9714,7 @@ fn statFromPosix(st: *const posix.Stat) File.Stat {...@@ -9714,7 +9714,7 @@ fn statFromPosix(st: *const posix.Stat) File.Stat {
9714 return .{9714 return .{
9715 .inode = st.ino,9715 .inode = st.ino,
9716 .size = @bitCast(st.size),9716 .size = @bitCast(st.size),
9717 .mode = st.mode,9717 .permissions = .fromMode(st.mode),
9718 .kind = k: {9718 .kind = k: {
9719 const m = st.mode & posix.S.IFMT;9719 const m = st.mode & posix.S.IFMT;
9720 switch (m) {9720 switch (m) {
...@@ -10019,7 +10019,7 @@ fn lookupHosts(...@@ -10019,7 +10019,7 @@ fn lookupHosts(
10019 options: HostName.LookupOptions,10019 options: HostName.LookupOptions,
10020) !void {10020) !void {
10021 const t_io = io(t);10021 const t_io = io(t);
10022 const file = File.openAbsolute(t_io, "/etc/hosts", .{}) catch |err| switch (err) {10022 const file = Dir.openFileAbsolute(t_io, "/etc/hosts", .{}) catch |err| switch (err) {
10023 error.FileNotFound,10023 error.FileNotFound,
10024 error.NotDir,10024 error.NotDir,
10025 error.AccessDenied,10025 error.AccessDenied,
lib/std/Io/net/HostName.zig+1-1
...@@ -343,7 +343,7 @@ pub const ResolvConf = struct {...@@ -343,7 +343,7 @@ pub const ResolvConf = struct {
343 .attempts = 2,343 .attempts = 2,
344 };344 };
345345
346 const file = Io.File.openAbsolute(io, "/etc/resolv.conf", .{}) catch |err| switch (err) {346 const file = Io.Dir.openFileAbsolute(io, "/etc/resolv.conf", .{}) catch |err| switch (err) {
347 error.FileNotFound,347 error.FileNotFound,
348 error.NotDir,348 error.NotDir,
349 error.AccessDenied,349 error.AccessDenied,
lib/std/Io/test.zig+3-2
...@@ -114,7 +114,7 @@ test "setEndPos" {...@@ -114,7 +114,7 @@ test "setEndPos" {
114 try expect((try file.getPos()) == 100);114 try expect((try file.getPos()) == 100);
115}115}
116116
117test "updateTimes" {117test "setTimestamps" {
118 const io = testing.io;118 const io = testing.io;
119119
120 var tmp = tmpDir(.{});120 var tmp = tmpDir(.{});
...@@ -126,7 +126,8 @@ test "updateTimes" {...@@ -126,7 +126,8 @@ test "updateTimes" {
126126
127 const stat_old = try file.stat(io);127 const stat_old = try file.stat(io);
128 // Set atime and mtime to 5s before128 // Set atime and mtime to 5s before
129 try file.updateTimes(129 try file.setTimestamps(
130 io,
130 stat_old.atime.subDuration(.fromSeconds(5)),131 stat_old.atime.subDuration(.fromSeconds(5)),
131 stat_old.mtime.subDuration(.fromSeconds(5)),132 stat_old.mtime.subDuration(.fromSeconds(5)),
132 );133 );
lib/std/Io/tty.zig+5-4
...@@ -2,6 +2,7 @@ const builtin = @import("builtin");...@@ -2,6 +2,7 @@ const builtin = @import("builtin");
2const native_os = builtin.os.tag;2const native_os = builtin.os.tag;
33
4const std = @import("std");4const std = @import("std");
5const Io = std.Io;
5const File = std.Io.File;6const File = std.Io.File;
6const process = std.process;7const process = std.process;
7const windows = std.os.windows;8const windows = std.os.windows;
...@@ -39,7 +40,7 @@ pub const Config = union(enum) {...@@ -39,7 +40,7 @@ pub const Config = union(enum) {
39 /// This includes feature checks for ANSI escape codes and the Windows console API, as well as40 /// This includes feature checks for ANSI escape codes and the Windows console API, as well as
40 /// respecting the `NO_COLOR` and `CLICOLOR_FORCE` environment variables to override the default.41 /// respecting the `NO_COLOR` and `CLICOLOR_FORCE` environment variables to override the default.
41 /// Will attempt to enable ANSI escape code support if necessary/possible.42 /// Will attempt to enable ANSI escape code support if necessary/possible.
42 pub fn detect(file: File) Config {43 pub fn detect(io: Io, file: File) Config {
43 const force_color: ?bool = if (builtin.os.tag == .wasi)44 const force_color: ?bool = if (builtin.os.tag == .wasi)
44 null // wasi does not support environment variables45 null // wasi does not support environment variables
45 else if (process.hasNonEmptyEnvVarConstant("NO_COLOR"))46 else if (process.hasNonEmptyEnvVarConstant("NO_COLOR"))
...@@ -51,7 +52,7 @@ pub const Config = union(enum) {...@@ -51,7 +52,7 @@ pub const Config = union(enum) {
5152
52 if (force_color == false) return .no_color;53 if (force_color == false) return .no_color;
5354
54 if (file.enableAnsiEscapeCodes()) |_| {55 if (file.enableAnsiEscapeCodes(io)) |_| {
55 return .escape_codes;56 return .escape_codes;
56 } else |_| {}57 } else |_| {}
5758
...@@ -74,9 +75,9 @@ pub const Config = union(enum) {...@@ -74,9 +75,9 @@ pub const Config = union(enum) {
74 reset_attributes: u16,75 reset_attributes: u16,
75 };76 };
7677
77 pub const SetColorError = std.os.windows.SetConsoleTextAttributeError || std.Io.Writer.Error;78 pub const SetColorError = std.os.windows.SetConsoleTextAttributeError || Io.Writer.Error;
7879
79 pub fn setColor(conf: Config, w: *std.Io.Writer, color: Color) SetColorError!void {80 pub fn setColor(conf: Config, w: *Io.Writer, color: Color) SetColorError!void {
80 nosuspend switch (conf) {81 nosuspend switch (conf) {
81 .no_color => return,82 .no_color => return,
82 .escape_codes => {83 .escape_codes => {
lib/std/debug.zig+3-1
...@@ -286,11 +286,13 @@ pub fn unlockStdErr() void {...@@ -286,11 +286,13 @@ pub fn unlockStdErr() void {
286pub fn lockStderrWriter(buffer: []u8) struct { *Writer, tty.Config } {286pub fn lockStderrWriter(buffer: []u8) struct { *Writer, tty.Config } {
287 const global = struct {287 const global = struct {
288 var conf: ?tty.Config = null;288 var conf: ?tty.Config = null;
289 var single_threaded_io: Io.Threaded = .init_single_threaded;
289 };290 };
291 const io = global.single_threaded_io.io();
290 const w = std.Progress.lockStderrWriter(buffer);292 const w = std.Progress.lockStderrWriter(buffer);
291 // The stderr lock also locks access to `global.conf`.293 // The stderr lock also locks access to `global.conf`.
292 if (global.conf == null) {294 if (global.conf == null) {
293 global.conf = .detect(.stderr());295 global.conf = .detect(io, .stderr());
294 }296 }
295 return .{ w, global.conf.? };297 return .{ w, global.conf.? };
296}298}
lib/std/debug/Info.zig+4-3
...@@ -42,7 +42,7 @@ pub fn load(...@@ -42,7 +42,7 @@ pub fn load(
42 var file = try path.root_dir.handle.openFile(io, path.sub_path, .{});42 var file = try path.root_dir.handle.openFile(io, path.sub_path, .{});
43 defer file.close(io);43 defer file.close(io);
4444
45 var elf_file: ElfFile = try .load(gpa, file, null, &.none);45 var elf_file: ElfFile = try .load(gpa, io, file, null, &.none);
46 errdefer elf_file.deinit(gpa);46 errdefer elf_file.deinit(gpa);
4747
48 if (elf_file.dwarf == null) return error.MissingDebugInfo;48 if (elf_file.dwarf == null) return error.MissingDebugInfo;
...@@ -58,7 +58,7 @@ pub fn load(...@@ -58,7 +58,7 @@ pub fn load(
58 const path_str = try path.toString(gpa);58 const path_str = try path.toString(gpa);
59 defer gpa.free(path_str);59 defer gpa.free(path_str);
6060
61 var macho_file: MachOFile = try .load(gpa, path_str, arch);61 var macho_file: MachOFile = try .load(gpa, io, path_str, arch);
62 errdefer macho_file.deinit(gpa);62 errdefer macho_file.deinit(gpa);
6363
64 return .{64 return .{
...@@ -85,6 +85,7 @@ pub const ResolveAddressesError = Coverage.ResolveAddressesDwarfError || error{U...@@ -85,6 +85,7 @@ pub const ResolveAddressesError = Coverage.ResolveAddressesDwarfError || error{U
85pub fn resolveAddresses(85pub fn resolveAddresses(
86 info: *Info,86 info: *Info,
87 gpa: Allocator,87 gpa: Allocator,
88 io: Io,
88 /// Asserts the addresses are in ascending order.89 /// Asserts the addresses are in ascending order.
89 sorted_pc_addrs: []const u64,90 sorted_pc_addrs: []const u64,
90 /// Asserts its length equals length of `sorted_pc_addrs`.91 /// Asserts its length equals length of `sorted_pc_addrs`.
...@@ -97,7 +98,7 @@ pub fn resolveAddresses(...@@ -97,7 +98,7 @@ pub fn resolveAddresses(
97 // Resolving all of the addresses at once unfortunately isn't so easy in Mach-O binaries98 // Resolving all of the addresses at once unfortunately isn't so easy in Mach-O binaries
98 // due to split debug information. For now, we'll just resolve the addreses one by one.99 // due to split debug information. For now, we'll just resolve the addreses one by one.
99 for (sorted_pc_addrs, output) |pc_addr, *src_loc| {100 for (sorted_pc_addrs, output) |pc_addr, *src_loc| {
100 const dwarf, const dwarf_pc_addr = mf.getDwarfForAddress(gpa, pc_addr) catch |err| switch (err) {101 const dwarf, const dwarf_pc_addr = mf.getDwarfForAddress(gpa, io, pc_addr) catch |err| switch (err) {
101 error.InvalidMachO, error.InvalidDwarf => return error.InvalidDebugInfo,102 error.InvalidMachO, error.InvalidDwarf => return error.InvalidDebugInfo,
102 else => |e| return e,103 else => |e| return e,
103 };104 };
lib/std/heap/debug_allocator.zig+27-12
...@@ -179,6 +179,8 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -179,6 +179,8 @@ pub fn DebugAllocator(comptime config: Config) type {
179 total_requested_bytes: @TypeOf(total_requested_bytes_init) = total_requested_bytes_init,179 total_requested_bytes: @TypeOf(total_requested_bytes_init) = total_requested_bytes_init,
180 requested_memory_limit: @TypeOf(requested_memory_limit_init) = requested_memory_limit_init,180 requested_memory_limit: @TypeOf(requested_memory_limit_init) = requested_memory_limit_init,
181 mutex: @TypeOf(mutex_init) = mutex_init,181 mutex: @TypeOf(mutex_init) = mutex_init,
182 /// Set this value differently to affect how errors and leaks are logged.
183 tty_config: std.Io.tty.Config = .no_color,
182184
183 const Self = @This();185 const Self = @This();
184186
...@@ -458,9 +460,9 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -458,9 +460,9 @@ pub fn DebugAllocator(comptime config: Config) type {
458460
459 /// Emits log messages for leaks and then returns the number of detected leaks (0 if no leaks were detected).461 /// Emits log messages for leaks and then returns the number of detected leaks (0 if no leaks were detected).
460 pub fn detectLeaks(self: *Self) usize {462 pub fn detectLeaks(self: *Self) usize {
461 var leaks: usize = 0;463 const tty_config = self.tty_config;
462464
463 const tty_config: std.Io.tty.Config = .detect(.stderr());465 var leaks: usize = 0;
464466
465 for (self.buckets, 0..) |init_optional_bucket, size_class_index| {467 for (self.buckets, 0..) |init_optional_bucket, size_class_index| {
466 var optional_bucket = init_optional_bucket;468 var optional_bucket = init_optional_bucket;
...@@ -533,10 +535,15 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -533,10 +535,15 @@ pub fn DebugAllocator(comptime config: Config) type {
533 @memset(addr_buf[@min(st.index, addr_buf.len)..], 0);535 @memset(addr_buf[@min(st.index, addr_buf.len)..], 0);
534 }536 }
535537
536 fn reportDoubleFree(ret_addr: usize, alloc_stack_trace: StackTrace, free_stack_trace: StackTrace) void {538 fn reportDoubleFree(
539 tty_config: std.Io.tty.Config,
540 ret_addr: usize,
541 alloc_stack_trace: StackTrace,
542 free_stack_trace: StackTrace,
543 ) void {
544 @branchHint(.cold);
537 var addr_buf: [stack_n]usize = undefined;545 var addr_buf: [stack_n]usize = undefined;
538 const second_free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = ret_addr }, &addr_buf);546 const second_free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = ret_addr }, &addr_buf);
539 const tty_config: std.Io.tty.Config = .detect(.stderr());
540 log.err("Double free detected. Allocation: {f} First free: {f} Second free: {f}", .{547 log.err("Double free detected. Allocation: {f} First free: {f} Second free: {f}", .{
541 std.debug.FormatStackTrace{548 std.debug.FormatStackTrace{
542 .stack_trace = alloc_stack_trace,549 .stack_trace = alloc_stack_trace,
...@@ -580,7 +587,7 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -580,7 +587,7 @@ pub fn DebugAllocator(comptime config: Config) type {
580587
581 if (config.retain_metadata and entry.value_ptr.freed) {588 if (config.retain_metadata and entry.value_ptr.freed) {
582 if (config.safety) {589 if (config.safety) {
583 reportDoubleFree(ret_addr, entry.value_ptr.getStackTrace(.alloc), entry.value_ptr.getStackTrace(.free));590 reportDoubleFree(self.tty_config, ret_addr, entry.value_ptr.getStackTrace(.alloc), entry.value_ptr.getStackTrace(.free));
584 @panic("Unrecoverable double free");591 @panic("Unrecoverable double free");
585 } else {592 } else {
586 unreachable;593 unreachable;
...@@ -588,9 +595,10 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -588,9 +595,10 @@ pub fn DebugAllocator(comptime config: Config) type {
588 }595 }
589596
590 if (config.safety and old_mem.len != entry.value_ptr.bytes.len) {597 if (config.safety and old_mem.len != entry.value_ptr.bytes.len) {
598 @branchHint(.cold);
591 var addr_buf: [stack_n]usize = undefined;599 var addr_buf: [stack_n]usize = undefined;
592 const free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = ret_addr }, &addr_buf);600 const free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = ret_addr }, &addr_buf);
593 const tty_config: std.Io.tty.Config = .detect(.stderr());601 const tty_config = self.tty_config;
594 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{602 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{
595 entry.value_ptr.bytes.len,603 entry.value_ptr.bytes.len,
596 old_mem.len,604 old_mem.len,
...@@ -693,7 +701,7 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -693,7 +701,7 @@ pub fn DebugAllocator(comptime config: Config) type {
693701
694 if (config.retain_metadata and entry.value_ptr.freed) {702 if (config.retain_metadata and entry.value_ptr.freed) {
695 if (config.safety) {703 if (config.safety) {
696 reportDoubleFree(ret_addr, entry.value_ptr.getStackTrace(.alloc), entry.value_ptr.getStackTrace(.free));704 reportDoubleFree(self.tty_config, ret_addr, entry.value_ptr.getStackTrace(.alloc), entry.value_ptr.getStackTrace(.free));
697 return;705 return;
698 } else {706 } else {
699 unreachable;707 unreachable;
...@@ -701,9 +709,10 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -701,9 +709,10 @@ pub fn DebugAllocator(comptime config: Config) type {
701 }709 }
702710
703 if (config.safety and old_mem.len != entry.value_ptr.bytes.len) {711 if (config.safety and old_mem.len != entry.value_ptr.bytes.len) {
712 @branchHint(.cold);
704 var addr_buf: [stack_n]usize = undefined;713 var addr_buf: [stack_n]usize = undefined;
705 const free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = ret_addr }, &addr_buf);714 const free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = ret_addr }, &addr_buf);
706 const tty_config: std.Io.tty.Config = .detect(.stderr());715 const tty_config = self.tty_config;
707 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{716 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{
708 entry.value_ptr.bytes.len,717 entry.value_ptr.bytes.len,
709 old_mem.len,718 old_mem.len,
...@@ -915,6 +924,7 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -915,6 +924,7 @@ pub fn DebugAllocator(comptime config: Config) type {
915 if (!is_used) {924 if (!is_used) {
916 if (config.safety) {925 if (config.safety) {
917 reportDoubleFree(926 reportDoubleFree(
927 self.tty_config,
918 return_address,928 return_address,
919 bucketStackTrace(bucket, slot_count, slot_index, .alloc),929 bucketStackTrace(bucket, slot_count, slot_index, .alloc),
920 bucketStackTrace(bucket, slot_count, slot_index, .free),930 bucketStackTrace(bucket, slot_count, slot_index, .free),
...@@ -935,7 +945,8 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -935,7 +945,8 @@ pub fn DebugAllocator(comptime config: Config) type {
935 var addr_buf: [stack_n]usize = undefined;945 var addr_buf: [stack_n]usize = undefined;
936 const free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = return_address }, &addr_buf);946 const free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = return_address }, &addr_buf);
937 if (old_memory.len != requested_size) {947 if (old_memory.len != requested_size) {
938 const tty_config: std.Io.tty.Config = .detect(.stderr());948 @branchHint(.cold);
949 const tty_config = self.tty_config;
939 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{950 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{
940 requested_size,951 requested_size,
941 old_memory.len,952 old_memory.len,
...@@ -950,7 +961,8 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -950,7 +961,8 @@ pub fn DebugAllocator(comptime config: Config) type {
950 });961 });
951 }962 }
952 if (alignment != slot_alignment) {963 if (alignment != slot_alignment) {
953 const tty_config: std.Io.tty.Config = .detect(.stderr());964 @branchHint(.cold);
965 const tty_config = self.tty_config;
954 log.err("Allocation alignment {d} does not match free alignment {d}. Allocation: {f} Free: {f}", .{966 log.err("Allocation alignment {d} does not match free alignment {d}. Allocation: {f} Free: {f}", .{
955 slot_alignment.toByteUnits(),967 slot_alignment.toByteUnits(),
956 alignment.toByteUnits(),968 alignment.toByteUnits(),
...@@ -1028,6 +1040,7 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -1028,6 +1040,7 @@ pub fn DebugAllocator(comptime config: Config) type {
1028 const is_used = @as(u1, @truncate(used_byte.* >> used_bit_index)) != 0;1040 const is_used = @as(u1, @truncate(used_byte.* >> used_bit_index)) != 0;
1029 if (!is_used) {1041 if (!is_used) {
1030 reportDoubleFree(1042 reportDoubleFree(
1043 self.tty_config,
1031 return_address,1044 return_address,
1032 bucketStackTrace(bucket, slot_count, slot_index, .alloc),1045 bucketStackTrace(bucket, slot_count, slot_index, .alloc),
1033 bucketStackTrace(bucket, slot_count, slot_index, .free),1046 bucketStackTrace(bucket, slot_count, slot_index, .free),
...@@ -1044,7 +1057,8 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -1044,7 +1057,8 @@ pub fn DebugAllocator(comptime config: Config) type {
1044 var addr_buf: [stack_n]usize = undefined;1057 var addr_buf: [stack_n]usize = undefined;
1045 const free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = return_address }, &addr_buf);1058 const free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = return_address }, &addr_buf);
1046 if (memory.len != requested_size) {1059 if (memory.len != requested_size) {
1047 const tty_config: std.Io.tty.Config = .detect(.stderr());1060 @branchHint(.cold);
1061 const tty_config = self.tty_config;
1048 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{1062 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{
1049 requested_size,1063 requested_size,
1050 memory.len,1064 memory.len,
...@@ -1059,7 +1073,8 @@ pub fn DebugAllocator(comptime config: Config) type {...@@ -1059,7 +1073,8 @@ pub fn DebugAllocator(comptime config: Config) type {
1059 });1073 });
1060 }1074 }
1061 if (alignment != slot_alignment) {1075 if (alignment != slot_alignment) {
1062 const tty_config: std.Io.tty.Config = .detect(.stderr());1076 @branchHint(.cold);
1077 const tty_config = self.tty_config;
1063 log.err("Allocation alignment {d} does not match free alignment {d}. Allocation: {f} Free: {f}", .{1078 log.err("Allocation alignment {d} does not match free alignment {d}. Allocation: {f} Free: {f}", .{
1064 slot_alignment.toByteUnits(),1079 slot_alignment.toByteUnits(),
1065 alignment.toByteUnits(),1080 alignment.toByteUnits(),
lib/std/process/Child.zig+1-1
...@@ -470,7 +470,7 @@ pub fn run(allocator: Allocator, io: Io, args: struct {...@@ -470,7 +470,7 @@ pub fn run(allocator: Allocator, io: Io, args: struct {
470 return .{470 return .{
471 .stdout = try stdout.toOwnedSlice(allocator),471 .stdout = try stdout.toOwnedSlice(allocator),
472 .stderr = try stderr.toOwnedSlice(allocator),472 .stderr = try stderr.toOwnedSlice(allocator),
473 .term = try child.wait(),473 .term = try child.wait(io),
474 };474 };
475}475}
476476
lib/std/zig.zig+2-2
...@@ -60,9 +60,9 @@ pub const Color = enum {...@@ -60,9 +60,9 @@ pub const Color = enum {
60 .off => .no_color,60 .off => .no_color,
61 };61 };
62 }62 }
63 pub fn detectTtyConf(color: Color) Io.tty.Config {63 pub fn detectTtyConf(color: Color, io: Io) Io.tty.Config {
64 return switch (color) {64 return switch (color) {
65 .auto => .detect(.stderr()),65 .auto => .detect(io, .stderr()),
66 .on => .escape_codes,66 .on => .escape_codes,
67 .off => .no_color,67 .off => .no_color,
68 };68 };
src/link/Dwarf.zig+3-3
...@@ -51,10 +51,10 @@ pub const UpdateError = error{...@@ -51,10 +51,10 @@ pub const UpdateError = error{
51} ||51} ||
52 codegen.GenerateSymbolError ||52 codegen.GenerateSymbolError ||
53 Io.File.OpenError ||53 Io.File.OpenError ||
54 Io.File.SetEndPosError ||54 Io.File.LengthError ||
55 Io.File.CopyRangeError ||55 Io.File.CopyRangeError ||
56 Io.File.PReadError ||56 Io.File.ReadPositionalError ||
57 Io.File.PWriteError;57 Io.File.WritePositionalError;
5858
59pub const FlushError = UpdateError;59pub const FlushError = UpdateError;
6060
src/link/MappedFile.zig+1-1
...@@ -28,7 +28,7 @@ writers: std.SinglyLinkedList,...@@ -28,7 +28,7 @@ writers: std.SinglyLinkedList,
2828
29pub const growth_factor = 4;29pub const growth_factor = 4;
3030
31pub const Error = std.posix.MMapError || std.posix.MRemapError || Io.File.SetEndPosError || error{31pub const Error = std.posix.MMapError || std.posix.MRemapError || Io.File.LengthError || error{
32 NotFile,32 NotFile,
33 SystemResources,33 SystemResources,
34 IsDir,34 IsDir,
src/main.zig+14-9
...@@ -162,17 +162,20 @@ var debug_allocator: std.heap.DebugAllocator(.{...@@ -162,17 +162,20 @@ var debug_allocator: std.heap.DebugAllocator(.{
162 .stack_trace_frames = build_options.mem_leak_frames,162 .stack_trace_frames = build_options.mem_leak_frames,
163}) = .init;163}) = .init;
164164
165const use_debug_allocator = build_options.debug_gpa or
166 (native_os != .wasi and !builtin.link_libc and switch (builtin.mode) {
167 .Debug, .ReleaseSafe => true,
168 .ReleaseFast, .ReleaseSmall => false,
169 });
170
165pub fn main() anyerror!void {171pub fn main() anyerror!void {
166 const gpa, const is_debug = gpa: {172 const gpa = gpa: {
167 if (build_options.debug_gpa) break :gpa .{ debug_allocator.allocator(), true };173 if (use_debug_allocator) break :gpa debug_allocator.allocator();
168 if (native_os == .wasi) break :gpa .{ std.heap.wasm_allocator, false };174 if (native_os == .wasi) break :gpa std.heap.wasm_allocator;
169 if (builtin.link_libc) break :gpa .{ std.heap.c_allocator, false };175 if (builtin.link_libc) break :gpa std.heap.c_allocator;
170 break :gpa switch (builtin.mode) {176 break :gpa std.heap.smp_allocator;
171 .Debug, .ReleaseSafe => .{ debug_allocator.allocator(), true },
172 .ReleaseFast, .ReleaseSmall => .{ std.heap.smp_allocator, false },
173 };
174 };177 };
175 defer if (is_debug) {178 defer if (use_debug_allocator) {
176 _ = debug_allocator.deinit();179 _ = debug_allocator.deinit();
177 };180 };
178 var arena_instance = std.heap.ArenaAllocator.init(gpa);181 var arena_instance = std.heap.ArenaAllocator.init(gpa);
...@@ -244,6 +247,8 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -244,6 +247,8 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
244 threaded.stack_size = thread_stack_size;247 threaded.stack_size = thread_stack_size;
245 const io = threaded.io();248 const io = threaded.io();
246249
250 debug_allocator.tty_config = .detect(io, .stderr());
251
247 const cmd = args[1];252 const cmd = args[1];
248 const cmd_args = args[2..];253 const cmd_args = args[2..];
249 if (mem.eql(u8, cmd, "build-exe")) {254 if (mem.eql(u8, cmd, "build-exe")) {
test/link/macho.zig+2-1
...@@ -868,9 +868,10 @@ fn testLayout(b: *Build, opts: Options) *Step {...@@ -868,9 +868,10 @@ fn testLayout(b: *Build, opts: Options) *Step {
868}868}
869869
870fn testLinkDirectlyCppTbd(b: *Build, opts: Options) *Step {870fn testLinkDirectlyCppTbd(b: *Build, opts: Options) *Step {
871 const io = b.graph.io;
871 const test_step = addTestStep(b, "link-directly-cpp-tbd", opts);872 const test_step = addTestStep(b, "link-directly-cpp-tbd", opts);
872873
873 const sdk = std.zig.system.darwin.getSdk(b.allocator, &opts.target.result) orelse874 const sdk = std.zig.system.darwin.getSdk(b.allocator, io, &opts.target.result) orelse
874 @panic("macOS SDK is required to run the test");875 @panic("macOS SDK is required to run the test");
875876
876 const exe = addExecutable(b, opts, .{877 const exe = addExecutable(b, opts, .{
test/src/Cases.zig+3-2
...@@ -339,7 +339,7 @@ fn addFromDirInner(...@@ -339,7 +339,7 @@ fn addFromDirInner(
339 var it = try iterable_dir.walk(ctx.arena);339 var it = try iterable_dir.walk(ctx.arena);
340 var filenames: ArrayList([]const u8) = .empty;340 var filenames: ArrayList([]const u8) = .empty;
341341
342 while (try it.next()) |entry| {342 while (try it.next(io)) |entry| {
343 if (entry.kind != .file) continue;343 if (entry.kind != .file) continue;
344344
345 // Ignore stuff such as .swp files345 // Ignore stuff such as .swp files
...@@ -431,9 +431,10 @@ fn addFromDirInner(...@@ -431,9 +431,10 @@ fn addFromDirInner(
431 }431 }
432}432}
433433
434pub fn init(gpa: Allocator, arena: Allocator) Cases {434pub fn init(gpa: Allocator, arena: Allocator, io: Io) Cases {
435 return .{435 return .{
436 .gpa = gpa,436 .gpa = gpa,
437 .io = io,
437 .cases = .init(gpa),438 .cases = .init(gpa),
438 .arena = arena,439 .arena = arena,
439 };440 };
test/standalone/ios/build.zig+3-1
...@@ -23,7 +23,9 @@ pub fn build(b: *std.Build) void {...@@ -23,7 +23,9 @@ pub fn build(b: *std.Build) void {
23 }),23 }),
24 });24 });
2525
26 if (std.zig.system.darwin.getSdk(b.allocator, &target.result)) |sdk| {26 const io = b.graph.io;
27
28 if (std.zig.system.darwin.getSdk(b.allocator, io, &target.result)) |sdk| {
27 b.sysroot = sdk;29 b.sysroot = sdk;
28 exe.root_module.addSystemIncludePath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/usr/include" }) });30 exe.root_module.addSystemIncludePath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/usr/include" }) });
29 exe.root_module.addSystemFrameworkPath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/System/Library/Frameworks" }) });31 exe.root_module.addSystemFrameworkPath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/System/Library/Frameworks" }) });
test/standalone/self_exe_symlink/build.zig-4
...@@ -9,10 +9,6 @@ pub fn build(b: *std.Build) void {...@@ -9,10 +9,6 @@ pub fn build(b: *std.Build) void {
9 const optimize: std.builtin.OptimizeMode = .Debug;9 const optimize: std.builtin.OptimizeMode = .Debug;
10 const target = b.graph.host;10 const target = b.graph.host;
1111
12 // The test requires getFdPath in order to to get the path of the
13 // File returned by openSelfExe
14 if (!std.os.isGetFdPathSupportedOnTarget(target.result.os)) return;
15
16 const main = b.addExecutable(.{12 const main = b.addExecutable(.{
17 .name = "main",13 .name = "main",
18 .root_module = b.createModule(.{14 .root_module = b.createModule(.{
test/tests.zig+1-1
...@@ -2632,7 +2632,7 @@ pub fn addCases(...@@ -2632,7 +2632,7 @@ pub fn addCases(
2632 const gpa = b.allocator;2632 const gpa = b.allocator;
2633 const io = b.graph.io;2633 const io = b.graph.io;
26342634
2635 var cases = @import("src/Cases.zig").init(gpa, arena);2635 var cases = @import("src/Cases.zig").init(gpa, arena, io);
26362636
2637 var dir = try b.build_root.handle.openDir(io, "test/cases", .{ .iterate = true });2637 var dir = try b.build_root.handle.openDir(io, "test/cases", .{ .iterate = true });
2638 defer dir.close(io);2638 defer dir.close(io);