authorgravatar for mail@linusgroh.deLinus Groh <mail@linusgroh.de> 2026-05-03 21:09:17+01:00
committergravatar for mail@linusgroh.deLinus Groh <mail@linusgroh.de> 2026-05-03 21:42:16+01:00
logfcc0a5a913b586c56b3a9bb23f728d7bdd787b33
tree0b31dcfff6e7341c32753e75b744c4ee6c74405d
parentcd10ce9a67668bfdf1fd7ba57b499d93caa3c00f

std.mem.Allocator: Remove dupeZ() in favor of dupeSentinel()


21 files changed, 29 insertions(+), 35 deletions(-)

build.zig+1-1
......@@ -308,7 +308,7 @@ pub fn build(b: *std.Build) !void {
308308 },
309309 }
310310 };
311 const version = try b.allocator.dupeZ(u8, version_slice);
311 const version = try b.allocator.dupeSentinel(u8, version_slice, 0);
312312 exe_options.addOption([:0]const u8, "version", version);
313313
314314 if (enable_llvm) {
lib/compiler/aro/aro/CodeGen.zig+2-2
......@@ -894,7 +894,7 @@ fn genLval(c: *CodeGen, node_index: Node.Index) Error!Ir.Ref {
894894 }
895895 }
896896
897 const duped_name = try c.builder.arena.allocator().dupeZ(u8, slice);
897 const duped_name = try c.builder.arena.allocator().dupeSentinel(u8, slice, 0);
898898 const ref: Ir.Ref = @enumFromInt(c.builder.instructions.len);
899899 try c.builder.instructions.append(c.builder.gpa, .{ .tag = .symbol, .data = .{ .label = duped_name }, .ty = .ptr });
900900 return ref;
......@@ -1112,7 +1112,7 @@ fn genCall(c: *CodeGen, call: Node.Call) Error!Ir.Ref {
11121112 }
11131113 }
11141114
1115 const duped_name = try c.builder.arena.allocator().dupeZ(u8, slice);
1115 const duped_name = try c.builder.arena.allocator().dupeSentinel(u8, slice, 0);
11161116 const ref: Ir.Ref = @enumFromInt(c.builder.instructions.len);
11171117 try c.builder.instructions.append(c.builder.gpa, .{ .tag = .symbol, .data = .{ .label = duped_name }, .ty = .ptr });
11181118 break :blk ref;
lib/std/Build/Watch/FsEvents.zig+1-1
......@@ -195,7 +195,7 @@ pub fn setPaths(fse: *FsEvents, gpa: Allocator, steps: []const *std.Build.Step)
195195 } else {
196196 fse.watch_roots = try gpa.realloc(fse.watch_roots, need_dirs.count());
197197 for (fse.watch_roots, need_dirs.keys()) |*out, in| {
198 out.* = try paths_arena.dupeZ(u8, in);
198 out.* = try paths_arena.dupeSentinel(u8, in, 0);
199199 }
200200 }
201201 if (enable_debug_logs) {
lib/std/Io/Dir.zig+2-2
......@@ -944,7 +944,7 @@ pub const RealPathFileAllocError = RealPathFileError || Allocator.Error;
944944pub fn realPathFileAlloc(dir: Dir, io: Io, sub_path: []const u8, allocator: Allocator) RealPathFileAllocError![:0]u8 {
945945 var buffer: [max_path_bytes]u8 = undefined;
946946 const n = try realPathFile(dir, io, sub_path, &buffer);
947 return allocator.dupeZ(u8, buffer[0..n]);
947 return allocator.dupeSentinel(u8, buffer[0..n], 0);
948948}
949949
950950/// Same as `realPathFile` except `absolute_path` is asserted to be an absolute
......@@ -974,7 +974,7 @@ pub fn realPathFileAbsolute(io: Io, absolute_path: []const u8, out_buffer: []u8)
974974pub fn realPathFileAbsoluteAlloc(io: Io, absolute_path: []const u8, allocator: Allocator) RealPathFileAllocError![:0]u8 {
975975 var buffer: [max_path_bytes]u8 = undefined;
976976 const n = try realPathFileAbsolute(io, absolute_path, &buffer);
977 return allocator.dupeZ(u8, buffer[0..n]);
977 return allocator.dupeSentinel(u8, buffer[0..n], 0);
978978}
979979
980980pub const DeleteFileError = error{
lib/std/Io/Dispatch.zig+2-2
......@@ -4086,7 +4086,7 @@ fn processReplace(userdata: ?*anyopaque, options: process.ReplaceOptions) proces
40864086 const arena = arena_allocator.allocator();
40874087
40884088 const argv_buf = try arena.allocSentinel(?[*:0]const u8, options.argv.len, null);
4089 for (options.argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeZ(u8, arg)).ptr;
4089 for (options.argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeSentinel(u8, arg, 0)).ptr;
40904090
40914091 const env_block = env_block: {
40924092 const prog_fd: i32 = -1;
......@@ -4222,7 +4222,7 @@ fn spawn(ev: *Evented, options: process.SpawnOptions) process.SpawnError!Spawned
42224222 // Therefore, we do all the allocation for the execve() before the fork().
42234223 // This means we must do the null-termination of argv and env vars here.
42244224 const argv_buf = try arena.allocSentinel(?[*:0]const u8, options.argv.len, null);
4225 for (options.argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeZ(u8, arg)).ptr;
4225 for (options.argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeSentinel(u8, arg, 0)).ptr;
42264226
42274227 const env_block = env_block: {
42284228 const prog_fd: i32 = if (prog_pipe[1] == -1) -1 else prog_fileno;
lib/std/Io/Threaded.zig+2-2
......@@ -14954,7 +14954,7 @@ fn processReplace(userdata: ?*anyopaque, options: process.ReplaceOptions) proces
1495414954 const arena = arena_allocator.allocator();
1495514955
1495614956 const argv_buf = try arena.allocSentinel(?[*:0]const u8, options.argv.len, null);
14957 for (options.argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeZ(u8, arg)).ptr;
14957 for (options.argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeSentinel(u8, arg, 0)).ptr;
1495814958
1495914959 const env_block = env_block: {
1496014960 const prog_fd: i32 = -1;
......@@ -15061,7 +15061,7 @@ fn spawnPosix(t: *Threaded, options: process.SpawnOptions) process.SpawnError!Sp
1506115061 // Therefore, we do all the allocation for the execve() before the fork().
1506215062 // This means we must do the null-termination of argv and env vars here.
1506315063 const argv_buf = try arena.allocSentinel(?[*:0]const u8, options.argv.len, null);
15064 for (options.argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeZ(u8, arg)).ptr;
15064 for (options.argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeSentinel(u8, arg, 0)).ptr;
1506515065
1506615066 const prog_fileno = 3;
1506715067 comptime assert(@max(posix.STDIN_FILENO, posix.STDOUT_FILENO, posix.STDERR_FILENO) + 1 == prog_fileno);
lib/std/Io/Uring.zig+2-2
......@@ -4226,7 +4226,7 @@ fn processReplace(userdata: ?*anyopaque, options: process.ReplaceOptions) proces
42264226 const arena = arena_allocator.allocator();
42274227
42284228 const argv_buf = try arena.allocSentinel(?[*:0]const u8, options.argv.len, null);
4229 for (options.argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeZ(u8, arg)).ptr;
4229 for (options.argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeSentinel(u8, arg, 0)).ptr;
42304230
42314231 const env_block = env_block: {
42324232 const prog_fd: i32 = -1;
......@@ -4369,7 +4369,7 @@ fn spawn(ev: *Evented, options: process.SpawnOptions) process.SpawnError!Spawned
43694369 // Therefore, we do all the allocation for the execve() before the fork().
43704370 // This means we must do the null-termination of argv and env vars here.
43714371 const argv_buf = try arena.allocSentinel(?[*:0]const u8, options.argv.len, null);
4372 for (options.argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeZ(u8, arg)).ptr;
4372 for (options.argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeSentinel(u8, arg, 0)).ptr;
43734373
43744374 const env_block = env_block: {
43754375 const prog_fd: i32 = if (prog_pipe[1] == -1) -1 else prog_fileno;
lib/std/debug.zig+1-1
......@@ -517,7 +517,7 @@ pub fn defaultPanic(msg: []const u8, first_trace_addr: ?usize) noreturn {
517517
518518 if (uefi.system_table.boot_services) |bs| {
519519 // ExitData buffer must be allocated using boot_services.allocatePool (spec: page 220)
520 const exit_data = uefi.raw_pool_allocator.dupeZ(u16, exit_msg) catch @trap();
520 const exit_data = uefi.raw_pool_allocator.dupeSentinel(u16, exit_msg, 0) catch @trap();
521521 bs.exit(uefi.handle, .aborted, exit_data) catch {};
522522 }
523523 @trap();
lib/std/fs/test.zig+2-2
......@@ -135,7 +135,7 @@ const TestContext = struct {
135135 const allocator = self.arena.allocator();
136136 const transformed_path = try self.transform_fn(allocator, self.io, self.dir, relative_path);
137137 if (native_os == .windows) {
138 const transformed_sep_path = try allocator.dupeZ(u8, transformed_path);
138 const transformed_sep_path = try allocator.dupeSentinel(u8, transformed_path, 0);
139139 std.mem.replaceScalar(u8, transformed_sep_path, switch (self.path_sep) {
140140 '/' => '\\',
141141 '\\' => '/',
......@@ -153,7 +153,7 @@ const TestContext = struct {
153153 pub fn toCanonicalPathSep(self: *TestContext, path: [:0]const u8) ![:0]const u8 {
154154 if (native_os == .windows) {
155155 const allocator = self.arena.allocator();
156 const transformed_sep_path = try allocator.dupeZ(u8, path);
156 const transformed_sep_path = try allocator.dupeSentinel(u8, path, 0);
157157 std.mem.replaceScalar(u8, transformed_sep_path, '/', '\\');
158158 return transformed_sep_path;
159159 }
lib/std/mem.zig+1-1
......@@ -4964,7 +4964,7 @@ test isAligned {
49644964}
49654965
49664966test "freeing empty string with null-terminated sentinel" {
4967 const empty_string = try testing.allocator.dupeZ(u8, "");
4967 const empty_string = try testing.allocator.dupeSentinel(u8, "", 0);
49684968 testing.allocator.free(empty_string);
49694969}
49704970
lib/std/mem/Allocator.zig-6
......@@ -456,12 +456,6 @@ pub fn dupe(allocator: Allocator, comptime T: type, m: []const T) Error![]T {
456456 return new_buf;
457457}
458458
459/// Deprecated in favor of `dupeSentinel`
460/// Copies `m` to newly allocated memory, with a null-terminated element. Caller owns the memory.
461pub fn dupeZ(allocator: Allocator, comptime T: type, m: []const T) Error![:0]T {
462 return allocator.dupeSentinel(T, m, 0);
463}
464
465459/// Copies `m` to newly allocated memory, with a null-terminated element. Caller owns the memory.
466460pub fn dupeSentinel(
467461 allocator: Allocator,
lib/std/os/plan9.zig+1-1
......@@ -299,7 +299,7 @@ pub fn openat(dirfd: i32, path: [*:0]const u8, flags: u32, _: mode_t) usize {
299299 const dir_path = std.mem.span(@as([*:0]u8, @ptrCast(&dir_path_buf)));
300300 const total_path = std.fs.path.join(alloc, &.{ dir_path, std.mem.span(path) }) catch unreachable; // the allocation shouldn't fail because it should not exceed max_path_bytes
301301 fba.reset();
302 const total_path_z = alloc.dupeZ(u8, total_path) catch unreachable; // should not exceed max_path_bytes + 1
302 const total_path_z = alloc.dupeSentinel(u8, total_path, 0) catch unreachable; // should not exceed max_path_bytes + 1
303303 return open(total_path_z.ptr, flags);
304304}
305305
lib/std/process.zig+2-2
......@@ -85,7 +85,7 @@ pub fn currentPathAlloc(io: Io, allocator: Allocator) CurrentPathAllocError![:0]
8585 error.NameTooLong => unreachable,
8686 else => |e| return e,
8787 };
88 return allocator.dupeZ(u8, buffer[0..n]);
88 return allocator.dupeSentinel(u8, buffer[0..n], 0);
8989}
9090
9191test currentPathAlloc {
......@@ -734,7 +734,7 @@ pub fn executablePathAlloc(io: Io, allocator: Allocator) ExecutablePathAllocErro
734734 error.NameTooLong => unreachable,
735735 else => |e| return e,
736736 };
737 return allocator.dupeZ(u8, buffer[0..n]);
737 return allocator.dupeSentinel(u8, buffer[0..n], 0);
738738}
739739
740740pub const ExecutablePathError = ExecutablePathBaseError || error{NameTooLong};
lib/std/process/Environ.zig+1-1
......@@ -754,7 +754,7 @@ pub fn createPosixBlock(
754754 },
755755 .nothing => {},
756756 };
757 envp[envp_len] = try gpa.dupeZ(u8, mem.span(entry));
757 envp[envp_len] = try gpa.dupeSentinel(u8, mem.span(entry), 0);
758758 envp_len += 1;
759759 }
760760
lib/std/zig/LibCInstallation.zig+1-1
......@@ -70,7 +70,7 @@ pub fn parse(allocator: Allocator, io: Io, libc_file: []const u8, target: *const
7070 if (value.len == 0) {
7171 @field(self, field.name) = null;
7272 } else {
73 found_keys[i].allocated = try allocator.dupeZ(u8, value);
73 found_keys[i].allocated = try allocator.dupeSentinel(u8, value, 0);
7474 @field(self, field.name) = found_keys[i].allocated;
7575 }
7676 break;
src/Compilation.zig+1-1
......@@ -1869,7 +1869,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
18691869 const comp: *Compilation = comp: {
18701870 // We put the `Compilation` itself in the arena. Freeing the arena will free the module.
18711871 // It's initialized later after we prepare the initialization options.
1872 const root_name = try arena.dupeZ(u8, options.root_name);
1872 const root_name = try arena.dupeSentinel(u8, options.root_name, 0);
18731873
18741874 // The "any" values provided by resolved config only account for
18751875 // explicitly-provided settings. We now make them additionally account
src/codegen/llvm.zig+1-1
......@@ -918,7 +918,7 @@ pub const Object = struct {
918918 }
919919
920920 const target_triple_sentinel =
921 try o.gpa.dupeZ(u8, o.builder.target_triple.slice(&o.builder).?);
921 try o.gpa.dupeSentinel(u8, o.builder.target_triple.slice(&o.builder).?, 0);
922922 defer o.gpa.free(target_triple_sentinel);
923923
924924 const emit_asm_msg = options.asm_path orelse "(none)";
src/link/Lld.zig+2-2
......@@ -287,7 +287,7 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) !void {
287287 const comp = base.comp;
288288 const directory = base.emit.root_dir; // Just an alias to make it shorter to type.
289289 const full_out_path = try directory.join(arena, &[_][]const u8{base.emit.sub_path});
290 const full_out_path_z = try arena.dupeZ(u8, full_out_path);
290 const full_out_path_z = try arena.dupeSentinel(u8, full_out_path, 0);
291291 const opt_zcu = comp.zcu;
292292
293293 const zcu_obj_path: ?Cache.Path = if (opt_zcu != null) p: {
......@@ -326,7 +326,7 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) !void {
326326 object_files.appendAssumeCapacity(try key.status.success.object_path.toStringZ(arena));
327327 }
328328 for (comp.win32_resource_table.keys()) |key| {
329 object_files.appendAssumeCapacity(try arena.dupeZ(u8, key.status.success.res_path));
329 object_files.appendAssumeCapacity(try arena.dupeSentinel(u8, key.status.success.res_path, 0));
330330 }
331331 if (zcu_obj_path) |p| object_files.appendAssumeCapacity(try p.toStringZ(arena));
332332 if (compiler_rt_path) |p| object_files.appendAssumeCapacity(try p.toStringZ(arena));
src/main.zig+2-2
......@@ -5971,7 +5971,7 @@ extern "c" fn ZigLlvmAr_main(argc: c_int, argv: [*:null]?[*:0]u8) c_int;
59715971fn argsCopyZ(alloc: Allocator, args: []const []const u8) ![:null]?[*:0]u8 {
59725972 var argv = try alloc.allocSentinel(?[*:0]u8, args.len, null);
59735973 for (args, 0..) |arg, i| {
5974 argv[i] = try alloc.dupeZ(u8, arg); // TODO If there was an argsAllocZ we could avoid this allocation.
5974 argv[i] = try alloc.dupeSentinel(u8, arg, 0); // TODO If there was an argsAllocZ we could avoid this allocation.
59755975 }
59765976 return argv;
59775977}
......@@ -6601,7 +6601,7 @@ fn cmdDumpLlvmInts(
66016601 if (!build_options.have_llvm)
66026602 fatal("compiler does not use LLVM; cannot dump LLVM integer sizes", .{});
66036603
6604 const triple = try arena.dupeZ(u8, args[0]);
6604 const triple = try arena.dupeSentinel(u8, args[0], 0);
66056605
66066606 const llvm = @import("codegen/llvm/bindings.zig");
66076607
tools/docgen.zig+1-1
......@@ -679,7 +679,7 @@ fn tokenizeAndPrintRaw(
679679 raw_src: []const u8,
680680) !void {
681681 const src_non_terminated = mem.trim(u8, raw_src, " \r\n");
682 const src = try allocator.dupeZ(u8, src_non_terminated);
682 const src = try allocator.dupeSentinel(u8, src_non_terminated, 0);
683683
684684 try out.writeAll("<code>");
685685 var tokenizer = std.zig.Tokenizer.init(src);
tools/doctest.zig+1-1
......@@ -607,7 +607,7 @@ fn printSourceBlock(arena: Allocator, out: *Writer, source_bytes: []const u8, na
607607
608608fn tokenizeAndPrint(arena: Allocator, out: *Writer, raw_src: []const u8) !void {
609609 const src_non_terminated = mem.trim(u8, raw_src, " \r\n");
610 const src = try arena.dupeZ(u8, src_non_terminated);
610 const src = try arena.dupeSentinel(u8, src_non_terminated, 0);
611611
612612 try out.writeAll("<code>");
613613 var tokenizer = std.zig.Tokenizer.init(src);