authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-06 19:34:52+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-06 19:34:52+02:00
log3d56df1716601440f580df3eee7e12bea44d919b
tree46ee7390ab7481c10d7640b7a21fe484393914fd
parent994547d19acfd8ed79983b5b928052e8b01601fa
parentfcc0a5a913b586c56b3a9bb23f728d7bdd787b33

Merge pull request 'std.fmt, std.mem.Allocator: Remove bufPrintZ()/dupeZ() in favor of bufPrintSentinel()/dupeSentinel()' (#35190) from linus/zig:deprecated-std-fmt-mem into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/35190 Reviewed-by: Andrew Kelley <andrew@ziglang.org>

22 files changed, 30 insertions(+), 41 deletions(-)

build.zig+1-1
......@@ -307,7 +307,7 @@ pub fn build(b: *std.Build) !void {
307307 },
308308 }
309309 };
310 const version = try b.allocator.dupeZ(u8, version_slice);
310 const version = try b.allocator.dupeSentinel(u8, version_slice, 0);
311311 exe_options.addOption([:0]const u8, "version", version);
312312
313313 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+3-3
......@@ -13851,7 +13851,7 @@ fn netLookupFallible(
1385113851 const name_c = name_buffer[0..name.len :0];
1385213852
1385313853 var port_buffer: [8]u8 = undefined;
13854 const port_c = std.fmt.bufPrintZ(&port_buffer, "{d}", .{options.port}) catch unreachable;
13854 const port_c = std.fmt.bufPrintSentinel(&port_buffer, "{d}", .{options.port}, 0) catch unreachable;
1385513855
1385613856 const hints: posix.addrinfo = .{
1385713857 .flags = .{ .CANONNAME = options.canonical_name_buffer != null, .NUMERICSERV = true },
......@@ -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
......@@ -520,7 +520,7 @@ pub fn defaultPanic(msg: []const u8, first_trace_addr: ?usize) noreturn {
520520
521521 if (uefi.system_table.boot_services) |bs| {
522522 // ExitData buffer must be allocated using boot_services.allocatePool (spec: page 220)
523 const exit_data = uefi.raw_pool_allocator.dupeZ(u16, exit_msg) catch @trap();
523 const exit_data = uefi.raw_pool_allocator.dupeSentinel(u16, exit_msg, 0) catch @trap();
524524 bs.exit(uefi.handle, .aborted, exit_data) catch {};
525525 }
526526 @trap();
lib/std/fmt.zig-5
......@@ -602,11 +602,6 @@ pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintErro
602602 return w.buffered();
603603}
604604
605/// Deprecated in favor of `bufPrintSentinel`
606pub fn bufPrintZ(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintError![:0]u8 {
607 return try bufPrintSentinel(buf, fmt, args, 0);
608}
609
610605pub fn bufPrintSentinel(
611606 buf: []u8,
612607 comptime fmt: []const u8,
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
......@@ -86,7 +86,7 @@ pub fn currentPathAlloc(io: Io, allocator: Allocator) CurrentPathAllocError![:0]
8686 error.NameTooLong => unreachable,
8787 else => |e| return e,
8888 };
89 return allocator.dupeZ(u8, buffer[0..n]);
89 return allocator.dupeSentinel(u8, buffer[0..n], 0);
9090}
9191
9292test currentPathAlloc {
......@@ -735,7 +735,7 @@ pub fn executablePathAlloc(io: Io, allocator: Allocator) ExecutablePathAllocErro
735735 error.NameTooLong => unreachable,
736736 else => |e| return e,
737737 };
738 return allocator.dupeZ(u8, buffer[0..n]);
738 return allocator.dupeSentinel(u8, buffer[0..n], 0);
739739}
740740
741741pub 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
......@@ -5969,7 +5969,7 @@ extern "c" fn ZigLlvmAr_main(argc: c_int, argv: [*:null]?[*:0]u8) c_int;
59695969fn argsCopyZ(alloc: Allocator, args: []const []const u8) ![:null]?[*:0]u8 {
59705970 var argv = try alloc.allocSentinel(?[*:0]u8, args.len, null);
59715971 for (args, 0..) |arg, i| {
5972 argv[i] = try alloc.dupeZ(u8, arg); // TODO If there was an argsAllocZ we could avoid this allocation.
5972 argv[i] = try alloc.dupeSentinel(u8, arg, 0); // TODO If there was an argsAllocZ we could avoid this allocation.
59735973 }
59745974 return argv;
59755975}
......@@ -6599,7 +6599,7 @@ fn cmdDumpLlvmInts(
65996599 if (!build_options.have_llvm)
66006600 fatal("compiler does not use LLVM; cannot dump LLVM integer sizes", .{});
66016601
6602 const triple = try arena.dupeZ(u8, args[0]);
6602 const triple = try arena.dupeSentinel(u8, args[0], 0);
66036603
66046604 const llvm = @import("codegen/llvm/bindings.zig");
66056605
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);