diff --git a/lib/std/Random.zig b/lib/std/Random.zig index 8c68bdf6daef..ae88d8b4fe7f 100644 --- a/lib/std/Random.zig +++ b/lib/std/Random.zig @@ -29,6 +29,9 @@ pub const RomuTrio = @import("Random/RomuTrio.zig"); pub const SplitMix64 = @import("Random/SplitMix64.zig"); pub const ziggurat = @import("Random/ziggurat.zig"); +/// Any comparison of this field may result in illegal behavior, since it may be set to +/// `undefined` in cases where the random implementation does not have any associated +/// state. ptr: *anyopaque, fillFn: *const fn (ptr: *anyopaque, buf: []u8) void, diff --git a/lib/std/mem/Allocator.zig b/lib/std/mem/Allocator.zig index 7cf201d4b169..bc3ef028b913 100644 --- a/lib/std/mem/Allocator.zig +++ b/lib/std/mem/Allocator.zig @@ -10,7 +10,10 @@ const builtin = @import("builtin"); pub const Error = error{OutOfMemory}; pub const Log2Align = math.Log2Int(usize); -// The type erased pointer to the allocator implementation +/// The type erased pointer to the allocator implementation. +/// Any comparison of this field may result in illegal behavior, since it may be set to +/// `undefined` in cases where the allocator implementation does not have any associated +/// state. ptr: *anyopaque, vtable: *const VTable, diff --git a/lib/std/process/Child.zig b/lib/std/process/Child.zig index 279620749689..8a4cab5e83e7 100644 --- a/lib/std/process/Child.zig +++ b/lib/std/process/Child.zig @@ -344,15 +344,17 @@ pub const RunResult = struct { stderr: []u8, }; -fn fifoToOwnedArrayList(fifo: *std.io.PollFifo) std.ArrayList(u8) { +fn writeFifoDataToArrayList(allocator: Allocator, list: *std.ArrayListUnmanaged(u8), fifo: *std.io.PollFifo) !void { if (fifo.head != 0) fifo.realign(); - const result = std.ArrayList(u8){ - .items = fifo.buf[0..fifo.count], - .capacity = fifo.buf.len, - .allocator = fifo.allocator, - }; - fifo.* = std.io.PollFifo.init(fifo.allocator); - return result; + if (list.capacity == 0) { + list.* = .{ + .items = fifo.buf[0..fifo.count], + .capacity = fifo.buf.len, + }; + fifo.* = std.io.PollFifo.init(fifo.allocator); + } else { + try list.appendSlice(allocator, fifo.buf[0..fifo.count]); + } } /// Collect the output from the process's stdout and stderr. Will return once all output @@ -362,21 +364,16 @@ fn fifoToOwnedArrayList(fifo: *std.io.PollFifo) std.ArrayList(u8) { /// The process must be started with stdout_behavior and stderr_behavior == .Pipe pub fn collectOutput( child: ChildProcess, - stdout: *std.ArrayList(u8), - stderr: *std.ArrayList(u8), + /// Used for `stdout` and `stderr`. + allocator: Allocator, + stdout: *std.ArrayListUnmanaged(u8), + stderr: *std.ArrayListUnmanaged(u8), max_output_bytes: usize, ) !void { assert(child.stdout_behavior == .Pipe); assert(child.stderr_behavior == .Pipe); - // we could make this work with multiple allocators but YAGNI - if (stdout.allocator.ptr != stderr.allocator.ptr or - stdout.allocator.vtable != stderr.allocator.vtable) - { - unreachable; // ChildProcess.collectOutput only supports 1 allocator - } - - var poller = std.io.poll(stdout.allocator, enum { stdout, stderr }, .{ + var poller = std.io.poll(allocator, enum { stdout, stderr }, .{ .stdout = child.stdout.?, .stderr = child.stderr.?, }); @@ -389,8 +386,8 @@ pub fn collectOutput( return error.StderrStreamTooLong; } - stdout.* = fifoToOwnedArrayList(poller.fifo(.stdout)); - stderr.* = fifoToOwnedArrayList(poller.fifo(.stderr)); + try writeFifoDataToArrayList(allocator, stdout, poller.fifo(.stdout)); + try writeFifoDataToArrayList(allocator, stderr, poller.fifo(.stderr)); } pub const RunError = posix.GetCwdError || posix.ReadError || SpawnError || posix.PollError || error{ @@ -420,22 +417,20 @@ pub fn run(args: struct { child.expand_arg0 = args.expand_arg0; child.progress_node = args.progress_node; - var stdout = std.ArrayList(u8).init(args.allocator); - var stderr = std.ArrayList(u8).init(args.allocator); - errdefer { - stdout.deinit(); - stderr.deinit(); - } + var stdout: std.ArrayListUnmanaged(u8) = .empty; + errdefer stdout.deinit(args.allocator); + var stderr: std.ArrayListUnmanaged(u8) = .empty; + errdefer stderr.deinit(args.allocator); try child.spawn(); errdefer { _ = child.kill() catch {}; } - try child.collectOutput(&stdout, &stderr, args.max_output_bytes); + try child.collectOutput(args.allocator, &stdout, &stderr, args.max_output_bytes); return RunResult{ - .stdout = try stdout.toOwnedSlice(), - .stderr = try stderr.toOwnedSlice(), + .stdout = try stdout.toOwnedSlice(args.allocator), + .stderr = try stderr.toOwnedSlice(args.allocator), .term = try child.wait(), }; }