authorgravatar for andrew.kraevskii@gmail.comAndrew Kraevskiii <andrew.kraevskii@gmail.com> 2026-04-22 19:35:46+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-04-22 19:35:46+02:00
logbbab366b780e76a0bc96f51cd28a4ca754dfac0a
tree9be371898f11448d98048c77f31a07ecf036bcd2
parent03955476ad9d838850392a0d5a7baa6beea3452b

Audit usages of toOwnedSlice (#32001)

Followup to #30769 I grepped for `try .*toOwnedSlice` and checked all of them by hand. Fixes a bunch of memory leaks removes usages or `errdefer` and `vars` in some places. I also switched array_list.Managed to ArrayList where it was convenient. Reviewed-on: https://codeberg.org/ziglang/zig/pulls/32001 Reviewed-by: Andrew Kelley <andrew@ziglang.org>

20 files changed, 197 insertions(+), 181 deletions(-)

lib/compiler/translate-c/ast.zig+5-2
...@@ -863,11 +863,14 @@ pub fn render(gpa: Allocator, nodes: []const Node) !std.zig.Ast {...@@ -863,11 +863,14 @@ pub fn render(gpa: Allocator, nodes: []const Node) !std.zig.Ast {
863 .start = @as(u32, @intCast(ctx.buf.items.len)),863 .start = @as(u32, @intCast(ctx.buf.items.len)),
864 });864 });
865865
866 try ctx.buf.shrinkToLenSentinel(gpa);
867 try ctx.extra_data.shrinkToLen(gpa);
868
866 return .{869 return .{
867 .source = try ctx.buf.toOwnedSliceSentinel(gpa, 0),870 .source = ctx.buf.toOwnedSliceSentinelAssert(0),
868 .tokens = ctx.tokens.toOwnedSlice(),871 .tokens = ctx.tokens.toOwnedSlice(),
869 .nodes = ctx.nodes.toOwnedSlice(),872 .nodes = ctx.nodes.toOwnedSlice(),
870 .extra_data = try ctx.extra_data.toOwnedSlice(gpa),873 .extra_data = ctx.extra_data.toOwnedSliceAssert(),
871 .errors = &.{},874 .errors = &.{},
872 .mode = .zig,875 .mode = .zig,
873 };876 };
lib/docs/wasm/markdown/Parser.zig+5-9
...@@ -311,17 +311,13 @@ pub fn endInput(p: *Parser) Allocator.Error!Document {...@@ -311,17 +311,13 @@ pub fn endInput(p: *Parser) Allocator.Error!Document {
311 p.scratch_string.items.len = 0;311 p.scratch_string.items.len = 0;
312 p.scratch_extra.items.len = 0;312 p.scratch_extra.items.len = 0;
313313
314 var nodes = p.nodes.toOwnedSlice();314 try p.extra.shrinkToLen(p.allocator);
315 errdefer nodes.deinit(p.allocator);315 try p.string_bytes.shrinkToLen(p.allocator);
316 const extra = try p.extra.toOwnedSlice(p.allocator);
317 errdefer p.allocator.free(extra);
318 const string_bytes = try p.string_bytes.toOwnedSlice(p.allocator);
319 errdefer p.allocator.free(string_bytes);
320316
321 return .{317 return .{
322 .nodes = nodes,318 .nodes = p.nodes.toOwnedSlice(),
323 .extra = extra,319 .extra = p.extra.toOwnedSliceAssert(),
324 .string_bytes = string_bytes,320 .string_bytes = p.string_bytes.toOwnedSliceAssert(),
325 };321 };
326}322}
327323
lib/std/Build/Step/Compile.zig+18-15
...@@ -778,43 +778,46 @@ pub fn runPkgConfig(step: *Step, lib_name: []const u8) !PkgConfigResult {...@@ -778,43 +778,46 @@ pub fn runPkgConfig(step: *Step, lib_name: []const u8) !PkgConfigResult {
778 else => return err,778 else => return err,
779 };779 };
780780
781 var zig_cflags = std.array_list.Managed([]const u8).init(b.allocator);781 var zig_cflags: std.ArrayList([]const u8) = .empty;
782 defer zig_cflags.deinit();782 defer zig_cflags.deinit(b.allocator);
783 var zig_libs = std.array_list.Managed([]const u8).init(b.allocator);783 var zig_libs: std.ArrayList([]const u8) = .empty;
784 defer zig_libs.deinit();784 defer zig_libs.deinit(b.allocator);
785785
786 var arg_it = mem.tokenizeAny(u8, stdout, " \r\n\t");786 var arg_it = mem.tokenizeAny(u8, stdout, " \r\n\t");
787 while (arg_it.next()) |arg| {787 while (arg_it.next()) |arg| {
788 if (mem.eql(u8, arg, "-I")) {788 if (mem.eql(u8, arg, "-I")) {
789 const dir = arg_it.next() orelse return error.PkgConfigInvalidOutput;789 const dir = arg_it.next() orelse return error.PkgConfigInvalidOutput;
790 try zig_cflags.appendSlice(&[_][]const u8{ "-I", dir });790 try zig_cflags.appendSlice(b.allocator, &.{ "-I", dir });
791 } else if (mem.startsWith(u8, arg, "-I")) {791 } else if (mem.startsWith(u8, arg, "-I")) {
792 try zig_cflags.append(arg);792 try zig_cflags.append(b.allocator, arg);
793 } else if (mem.eql(u8, arg, "-L")) {793 } else if (mem.eql(u8, arg, "-L")) {
794 const dir = arg_it.next() orelse return error.PkgConfigInvalidOutput;794 const dir = arg_it.next() orelse return error.PkgConfigInvalidOutput;
795 try zig_libs.appendSlice(&[_][]const u8{ "-L", dir });795 try zig_libs.appendSlice(b.allocator, &.{ "-L", dir });
796 } else if (mem.startsWith(u8, arg, "-L")) {796 } else if (mem.startsWith(u8, arg, "-L")) {
797 try zig_libs.append(arg);797 try zig_libs.append(b.allocator, arg);
798 } else if (mem.eql(u8, arg, "-l")) {798 } else if (mem.eql(u8, arg, "-l")) {
799 const lib = arg_it.next() orelse return error.PkgConfigInvalidOutput;799 const lib = arg_it.next() orelse return error.PkgConfigInvalidOutput;
800 try zig_libs.appendSlice(&[_][]const u8{ "-l", lib });800 try zig_libs.appendSlice(b.allocator, &.{ "-l", lib });
801 } else if (mem.startsWith(u8, arg, "-l")) {801 } else if (mem.startsWith(u8, arg, "-l")) {
802 try zig_libs.append(arg);802 try zig_libs.append(b.allocator, arg);
803 } else if (mem.eql(u8, arg, "-D")) {803 } else if (mem.eql(u8, arg, "-D")) {
804 const macro = arg_it.next() orelse return error.PkgConfigInvalidOutput;804 const macro = arg_it.next() orelse return error.PkgConfigInvalidOutput;
805 try zig_cflags.appendSlice(&[_][]const u8{ "-D", macro });805 try zig_cflags.appendSlice(b.allocator, &.{ "-D", macro });
806 } else if (mem.startsWith(u8, arg, "-D")) {806 } else if (mem.startsWith(u8, arg, "-D")) {
807 try zig_cflags.append(arg);807 try zig_cflags.append(b.allocator, arg);
808 } else if (mem.startsWith(u8, arg, wl_rpath_prefix)) {808 } else if (mem.startsWith(u8, arg, wl_rpath_prefix)) {
809 try zig_cflags.appendSlice(&[_][]const u8{ "-rpath", arg[wl_rpath_prefix.len..] });809 try zig_cflags.appendSlice(b.allocator, &.{ "-rpath", arg[wl_rpath_prefix.len..] });
810 } else if (b.debug_pkg_config) {810 } else if (b.debug_pkg_config) {
811 return step.fail("unknown pkg-config flag '{s}'", .{arg});811 return step.fail("unknown pkg-config flag '{s}'", .{arg});
812 }812 }
813 }813 }
814814
815 try zig_cflags.shrinkToLen(b.allocator);
816 try zig_libs.shrinkToLen(b.allocator);
817
815 return .{818 return .{
816 .cflags = try zig_cflags.toOwnedSlice(),819 .cflags = zig_cflags.toOwnedSliceAssert(),
817 .libs = try zig_libs.toOwnedSlice(),820 .libs = zig_libs.toOwnedSliceAssert(),
818 };821 };
819}822}
820823
lib/std/Build/Step/Run.zig+2
...@@ -2699,7 +2699,9 @@ fn evalGeneric(run: *Run, spawn_options: process.SpawnOptions) !EvalGenericResul...@@ -2699,7 +2699,9 @@ fn evalGeneric(run: *Run, spawn_options: process.SpawnOptions) !EvalGenericResul
26992699
2700 try multi_reader.checkAnyError();2700 try multi_reader.checkAnyError();
27012701
2702 // TODO: this string can leak since alloc below can return error.
2702 stdout_bytes = try multi_reader.toOwnedSlice(0);2703 stdout_bytes = try multi_reader.toOwnedSlice(0);
2704 // TODO: this string can leak since its allocated using gpa and `try child.wait(io)` below can fail.
2703 stderr_bytes = try multi_reader.toOwnedSlice(1);2705 stderr_bytes = try multi_reader.toOwnedSlice(1);
2704 } else {2706 } else {
2705 var stdout_reader = stdout.readerStreaming(io, &.{});2707 var stdout_reader = stdout.readerStreaming(io, &.{});
lib/std/debug/Dwarf.zig+14-11
...@@ -879,16 +879,16 @@ fn parseAbbrevTable(di: *Dwarf, gpa: Allocator, offset: u64) !Abbrev.Table {...@@ -879,16 +879,16 @@ fn parseAbbrevTable(di: *Dwarf, gpa: Allocator, offset: u64) !Abbrev.Table {
879 var fr: Reader = .fixed(di.section(.debug_abbrev).?);879 var fr: Reader = .fixed(di.section(.debug_abbrev).?);
880 fr.seek = cast(usize, offset) orelse return bad();880 fr.seek = cast(usize, offset) orelse return bad();
881881
882 var abbrevs = std.array_list.Managed(Abbrev).init(gpa);882 var abbrevs: std.ArrayList(Abbrev) = .empty;
883 defer {883 defer {
884 for (abbrevs.items) |*abbrev| {884 for (abbrevs.items) |*abbrev| {
885 abbrev.deinit(gpa);885 abbrev.deinit(gpa);
886 }886 }
887 abbrevs.deinit();887 abbrevs.deinit(gpa);
888 }888 }
889889
890 var attrs = std.array_list.Managed(Abbrev.Attr).init(gpa);890 var attrs: std.ArrayList(Abbrev.Attr) = .empty;
891 defer attrs.deinit();891 defer attrs.deinit(gpa);
892892
893 while (true) {893 while (true) {
894 const code = try fr.takeLeb128(u64);894 const code = try fr.takeLeb128(u64);
...@@ -900,7 +900,7 @@ fn parseAbbrevTable(di: *Dwarf, gpa: Allocator, offset: u64) !Abbrev.Table {...@@ -900,7 +900,7 @@ fn parseAbbrevTable(di: *Dwarf, gpa: Allocator, offset: u64) !Abbrev.Table {
900 const attr_id = try fr.takeLeb128(u64);900 const attr_id = try fr.takeLeb128(u64);
901 const form_id = try fr.takeLeb128(u64);901 const form_id = try fr.takeLeb128(u64);
902 if (attr_id == 0 and form_id == 0) break;902 if (attr_id == 0 and form_id == 0) break;
903 try attrs.append(.{903 try attrs.append(gpa, .{
904 .id = attr_id,904 .id = attr_id,
905 .form_id = form_id,905 .form_id = form_id,
906 .payload = switch (form_id) {906 .payload = switch (form_id) {
...@@ -909,18 +909,18 @@ fn parseAbbrevTable(di: *Dwarf, gpa: Allocator, offset: u64) !Abbrev.Table {...@@ -909,18 +909,18 @@ fn parseAbbrevTable(di: *Dwarf, gpa: Allocator, offset: u64) !Abbrev.Table {
909 },909 },
910 });910 });
911 }911 }
912912 try abbrevs.ensureUnusedCapacity(gpa, 1);
913 try abbrevs.append(.{913 abbrevs.appendAssumeCapacity(.{
914 .code = code,914 .code = code,
915 .tag_id = tag_id,915 .tag_id = tag_id,
916 .has_children = has_children,916 .has_children = has_children,
917 .attrs = try attrs.toOwnedSlice(),917 .attrs = try attrs.toOwnedSlice(gpa),
918 });918 });
919 }919 }
920920
921 return .{921 return .{
922 .offset = offset,922 .offset = offset,
923 .abbrevs = try abbrevs.toOwnedSlice(),923 .abbrevs = try abbrevs.toOwnedSlice(gpa),
924 };924 };
925}925}
926926
...@@ -1204,10 +1204,13 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, endian: Endian, compile_unit:...@@ -1204,10 +1204,13 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, endian: Endian, compile_unit:
1204 }1204 }
1205 }{ .keys = line_table.keys() });1205 }{ .keys = line_table.keys() });
12061206
1207 try directories.shrinkToLen(gpa);
1208 try file_entries.shrinkToLen(gpa);
1209
1207 return .{1210 return .{
1208 .line_table = line_table,1211 .line_table = line_table,
1209 .directories = try directories.toOwnedSlice(gpa),1212 .directories = directories.toOwnedSliceAssert(),
1210 .files = try file_entries.toOwnedSlice(gpa),1213 .files = file_entries.toOwnedSliceAssert(),
1211 .version = version,1214 .version = version,
1212 };1215 };
1213}1216}
lib/std/debug/Pdb.zig+24-16
...@@ -83,8 +83,8 @@ pub fn parseDbiStream(self: *Pdb) !void {...@@ -83,8 +83,8 @@ pub fn parseDbiStream(self: *Pdb) !void {
83 const mod_info_size = header.mod_info_size;83 const mod_info_size = header.mod_info_size;
84 const section_contrib_size = header.section_contribution_size;84 const section_contrib_size = header.section_contribution_size;
8585
86 var modules = std.array_list.Managed(Module).init(gpa);86 var modules: std.ArrayList(Module) = .empty;
87 errdefer modules.deinit();87 defer modules.deinit(gpa);
8888
89 // Module Info Substream89 // Module Info Substream
90 var mod_info_offset: usize = 0;90 var mod_info_offset: usize = 0;
...@@ -113,11 +113,16 @@ pub fn parseDbiStream(self: *Pdb) !void {...@@ -113,11 +113,16 @@ pub fn parseDbiStream(self: *Pdb) !void {
113 this_record_len += march_forward_bytes;113 this_record_len += march_forward_bytes;
114 }114 }
115115
116 try modules.append(.{116 try modules.ensureUnusedCapacity(gpa, 1);
117 .mod_info = mod_info,117 const module_name_slice = try module_name.toOwnedSlice();
118 .module_name = try module_name.toOwnedSlice(),118 errdefer gpa.free(module_name_slice);
119 .obj_file_name = try obj_file_name.toOwnedSlice(),119 const obj_file_name_slice = try obj_file_name.toOwnedSlice();
120 errdefer gpa.free(obj_file_name_slice);
120121
122 modules.appendAssumeCapacity(.{
123 .mod_info = mod_info,
124 .module_name = module_name_slice,
125 .obj_file_name = obj_file_name_slice,
121 .populated = false,126 .populated = false,
122 .symbols = undefined,127 .symbols = undefined,
123 .subsect_info = undefined,128 .subsect_info = undefined,
...@@ -131,8 +136,8 @@ pub fn parseDbiStream(self: *Pdb) !void {...@@ -131,8 +136,8 @@ pub fn parseDbiStream(self: *Pdb) !void {
131 }136 }
132137
133 // Section Contribution Substream138 // Section Contribution Substream
134 var sect_contribs = std.array_list.Managed(pdb.SectionContribEntry).init(gpa);139 var sect_contribs: std.ArrayList(pdb.SectionContribEntry) = .empty;
135 errdefer sect_contribs.deinit();140 defer sect_contribs.deinit(gpa);
136141
137 var sect_cont_offset: usize = 0;142 var sect_cont_offset: usize = 0;
138 if (section_contrib_size != 0) {143 if (section_contrib_size != 0) {
...@@ -144,7 +149,7 @@ pub fn parseDbiStream(self: *Pdb) !void {...@@ -144,7 +149,7 @@ pub fn parseDbiStream(self: *Pdb) !void {
144 sect_cont_offset += @sizeOf(u32);149 sect_cont_offset += @sizeOf(u32);
145 }150 }
146 while (sect_cont_offset != section_contrib_size) {151 while (sect_cont_offset != section_contrib_size) {
147 const entry = try sect_contribs.addOne();152 const entry = try sect_contribs.addOne(gpa);
148 entry.* = try reader.takeStruct(pdb.SectionContribEntry, .little);153 entry.* = try reader.takeStruct(pdb.SectionContribEntry, .little);
149 sect_cont_offset += @sizeOf(pdb.SectionContribEntry);154 sect_cont_offset += @sizeOf(pdb.SectionContribEntry);
150155
...@@ -152,8 +157,11 @@ pub fn parseDbiStream(self: *Pdb) !void {...@@ -152,8 +157,11 @@ pub fn parseDbiStream(self: *Pdb) !void {
152 return error.InvalidDebugInfo;157 return error.InvalidDebugInfo;
153 }158 }
154159
155 self.modules = try modules.toOwnedSlice();160 try sect_contribs.shrinkToLen(gpa);
156 self.sect_contribs = try sect_contribs.toOwnedSlice();161 try modules.shrinkToLen(gpa);
162
163 self.sect_contribs = sect_contribs.toOwnedSliceAssert();
164 self.modules = modules.toOwnedSliceAssert();
157}165}
158166
159pub fn parseIpiStream(self: *Pdb) !void {167pub fn parseIpiStream(self: *Pdb) !void {
...@@ -1098,22 +1106,22 @@ const MsfStream = struct {...@@ -1098,22 +1106,22 @@ const MsfStream = struct {
1098 }1106 }
1099};1107};
11001108
1101fn readSparseBitVector(reader: *Io.Reader, allocator: Allocator) ![]u32 {1109fn readSparseBitVector(reader: *Io.Reader, gpa: Allocator) ![]u32 {
1102 const num_words = try reader.takeInt(u32, .little);1110 const num_words = try reader.takeInt(u32, .little);
1103 var list = std.array_list.Managed(u32).init(allocator);1111 var list: std.ArrayList(u32) = .empty;
1104 errdefer list.deinit();1112 defer list.deinit(gpa);
1105 var word_i: u32 = 0;1113 var word_i: u32 = 0;
1106 while (word_i != num_words) : (word_i += 1) {1114 while (word_i != num_words) : (word_i += 1) {
1107 const word = try reader.takeInt(u32, .little);1115 const word = try reader.takeInt(u32, .little);
1108 var bit_i: u5 = 0;1116 var bit_i: u5 = 0;
1109 while (true) : (bit_i += 1) {1117 while (true) : (bit_i += 1) {
1110 if (word & (@as(u32, 1) << bit_i) != 0) {1118 if (word & (@as(u32, 1) << bit_i) != 0) {
1111 try list.append(word_i * 32 + bit_i);1119 try list.append(gpa, word_i * 32 + bit_i);
1112 }1120 }
1113 if (bit_i == std.math.maxInt(u5)) break;1121 if (bit_i == std.math.maxInt(u5)) break;
1114 }1122 }
1115 }1123 }
1116 return try list.toOwnedSlice();1124 return try list.toOwnedSlice(gpa);
1117}1125}
11181126
1119fn blockCountFromSize(size: u32, block_size: u32) u32 {1127fn blockCountFromSize(size: u32, block_size: u32) u32 {
lib/std/zig/Ast.zig+5-7
...@@ -196,19 +196,17 @@ pub fn parseTokens(...@@ -196,19 +196,17 @@ pub fn parseTokens(
196 .zon => try parser.parseZon(),196 .zon => try parser.parseZon(),
197 }197 }
198198
199 const extra_data = try parser.extra_data.toOwnedSlice(gpa);199 try parser.extra_data.shrinkToLen(gpa);
200 errdefer gpa.free(extra_data);200 try parser.errors.shrinkToLen(gpa);
201 const errors = try parser.errors.toOwnedSlice(gpa);
202 errdefer gpa.free(errors);
203201
204 // TODO experiment with compacting the MultiArrayList slices here202 // TODO experiment with compacting the MultiArrayList slices here
205 return Ast{203 return .{
206 .source = source,204 .source = source,
207 .mode = mode,205 .mode = mode,
208 .tokens = tokens,206 .tokens = tokens,
209 .nodes = parser.nodes.toOwnedSlice(),207 .nodes = parser.nodes.toOwnedSlice(),
210 .extra_data = extra_data,208 .extra_data = parser.extra_data.toOwnedSliceAssert(),
211 .errors = errors,209 .errors = parser.errors.toOwnedSliceAssert(),
212 };210 };
213}211}
214212
lib/std/zig/AstGen.zig+5-2
...@@ -243,10 +243,13 @@ pub fn generate(gpa: Allocator, tree: Ast) Allocator.Error!Zir {...@@ -243,10 +243,13 @@ pub fn generate(gpa: Allocator, tree: Ast) Allocator.Error!Zir {
243 }243 }
244 }244 }
245245
246 try astgen.extra.shrinkToLen(gpa);
247 try astgen.string_bytes.shrinkToLen(gpa);
248
246 return .{249 return .{
247 .instructions = if (fatal) .empty else astgen.instructions.toOwnedSlice(),250 .instructions = if (fatal) .empty else astgen.instructions.toOwnedSlice(),
248 .string_bytes = try astgen.string_bytes.toOwnedSlice(gpa),251 .string_bytes = astgen.string_bytes.toOwnedSliceAssert(),
249 .extra = try astgen.extra.toOwnedSlice(gpa),252 .extra = astgen.extra.toOwnedSliceAssert(),
250 };253 };
251}254}
252255
lib/std/zig/ErrorBundle.zig+6-2
...@@ -397,9 +397,13 @@ pub const Wip = struct {...@@ -397,9 +397,13 @@ pub const Wip = struct {
397 });397 });
398 try wip.extra.appendSlice(gpa, @as([]const u32, @ptrCast(wip.root_list.items)));398 try wip.extra.appendSlice(gpa, @as([]const u32, @ptrCast(wip.root_list.items)));
399 wip.root_list.clearAndFree(gpa);399 wip.root_list.clearAndFree(gpa);
400
401 try wip.string_bytes.shrinkToLen(gpa);
402 try wip.extra.shrinkToLen(gpa);
403
400 return .{404 return .{
401 .string_bytes = try wip.string_bytes.toOwnedSlice(gpa),405 .string_bytes = wip.string_bytes.toOwnedSliceAssert(),
402 .extra = try wip.extra.toOwnedSlice(gpa),406 .extra = wip.extra.toOwnedSliceAssert(),
403 };407 };
404 }408 }
405409
lib/std/zig/ZonGen.zig+13-21
...@@ -67,38 +67,30 @@ pub fn generate(gpa: Allocator, tree: Ast, options: Options) Allocator.Error!Zoi...@@ -67,38 +67,30 @@ pub fn generate(gpa: Allocator, tree: Ast, options: Options) Allocator.Error!Zoi
67 }67 }
6868
69 if (zg.compile_errors.items.len > 0) {69 if (zg.compile_errors.items.len > 0) {
70 const string_bytes = try zg.string_bytes.toOwnedSlice(gpa);70 try zg.string_bytes.shrinkToLen(gpa);
71 errdefer gpa.free(string_bytes);71 try zg.compile_errors.shrinkToLen(gpa);
72 const compile_errors = try zg.compile_errors.toOwnedSlice(gpa);72 try zg.error_notes.shrinkToLen(gpa);
73 errdefer gpa.free(compile_errors);
74 const error_notes = try zg.error_notes.toOwnedSlice(gpa);
75 errdefer gpa.free(error_notes);
7673
77 return .{74 return .{
78 .nodes = .empty,75 .nodes = .empty,
79 .extra = &.{},76 .extra = &.{},
80 .limbs = &.{},77 .limbs = &.{},
81 .string_bytes = string_bytes,78 .string_bytes = zg.string_bytes.toOwnedSliceAssert(),
82 .compile_errors = compile_errors,79 .compile_errors = zg.compile_errors.toOwnedSliceAssert(),
83 .error_notes = error_notes,80 .error_notes = zg.error_notes.toOwnedSliceAssert(),
84 };81 };
85 } else {82 } else {
86 assert(zg.error_notes.items.len == 0);83 assert(zg.error_notes.items.len == 0);
8784
88 var nodes = zg.nodes.toOwnedSlice();85 try zg.extra.shrinkToLen(gpa);
89 errdefer nodes.deinit(gpa);86 try zg.limbs.shrinkToLen(gpa);
90 const extra = try zg.extra.toOwnedSlice(gpa);87 try zg.string_bytes.shrinkToLen(gpa);
91 errdefer gpa.free(extra);
92 const limbs = try zg.limbs.toOwnedSlice(gpa);
93 errdefer gpa.free(limbs);
94 const string_bytes = try zg.string_bytes.toOwnedSlice(gpa);
95 errdefer gpa.free(string_bytes);
9688
97 return .{89 return .{
98 .nodes = nodes,90 .nodes = zg.nodes.toOwnedSlice(),
99 .extra = extra,91 .extra = zg.extra.toOwnedSliceAssert(),
100 .limbs = limbs,92 .limbs = zg.limbs.toOwnedSliceAssert(),
101 .string_bytes = string_bytes,93 .string_bytes = zg.string_bytes.toOwnedSliceAssert(),
102 .compile_errors = &.{},94 .compile_errors = &.{},
103 .error_notes = &.{},95 .error_notes = &.{},
104 };96 };
src/Compilation.zig+10-15
...@@ -1200,37 +1200,32 @@ pub const CObject = struct {...@@ -1200,37 +1200,32 @@ pub const CObject = struct {
1200 .end_block => |block| switch (@as(BlockId, @enumFromInt(block.id))) {1200 .end_block => |block| switch (@as(BlockId, @enumFromInt(block.id))) {
1201 .Meta => {},1201 .Meta => {},
1202 .Diag => {1202 .Diag => {
1203 var wip_diag = stack.pop().?;1203 try stack.items[stack.items.len - 2].sub_diags.ensureUnusedCapacity(gpa, 1);
1204 errdefer wip_diag.deinit(gpa);1204 try stack.items[stack.items.len - 1].src_ranges.shrinkToLen(gpa);
12051205 try stack.items[stack.items.len - 1].sub_diags.shrinkToLen(gpa);
1206 const src_ranges = try wip_diag.src_ranges.toOwnedSlice(gpa);
1207 errdefer gpa.free(src_ranges);
12081206
1209 const sub_diags = try wip_diag.sub_diags.toOwnedSlice(gpa);1207 var wip_diag = stack.pop().?;
1210 errdefer {
1211 for (sub_diags) |*sub_diag| sub_diag.deinit(gpa);
1212 gpa.free(sub_diags);
1213 }
12141208
1215 try stack.items[stack.items.len - 1].sub_diags.append(gpa, .{1209 stack.items[stack.items.len - 1].sub_diags.appendAssumeCapacity(.{
1216 .level = wip_diag.level,1210 .level = wip_diag.level,
1217 .category = wip_diag.category,1211 .category = wip_diag.category,
1218 .msg = wip_diag.msg,1212 .msg = wip_diag.msg,
1219 .src_loc = wip_diag.src_loc,1213 .src_loc = wip_diag.src_loc,
1220 .src_ranges = src_ranges,1214 .src_ranges = wip_diag.src_ranges.toOwnedSliceAssert(),
1221 .sub_diags = sub_diags,1215 .sub_diags = wip_diag.sub_diags.toOwnedSliceAssert(),
1222 });1216 });
1223 },1217 },
1224 _ => {},1218 _ => {},
1225 },1219 },
1226 };1220 };
1221 assert(stack.items.len == 1);
1222 try stack.items[0].sub_diags.shrinkToLen(gpa);
12271223
1228 const bundle = try gpa.create(Bundle);1224 const bundle = try gpa.create(Bundle);
1229 assert(stack.items.len == 1);
1230 bundle.* = .{1225 bundle.* = .{
1231 .file_names = file_names,1226 .file_names = file_names,
1232 .category_names = category_names,1227 .category_names = category_names,
1233 .diags = try stack.items[0].sub_diags.toOwnedSlice(gpa),1228 .diags = stack.items[0].sub_diags.toOwnedSliceAssert(),
1234 };1229 };
1235 return bundle;1230 return bundle;
1236 }1231 }
src/codegen/aarch64.zig+17-16
...@@ -170,26 +170,27 @@ pub fn generate(...@@ -170,26 +170,27 @@ pub fn generate(
170 const prologue = isel.instructions.items.len;170 const prologue = isel.instructions.items.len;
171 const epilogue = try isel.layout(param_it, is_sysv_var_args, saved_gra_len, saved_vra_len, mod);171 const epilogue = try isel.layout(param_it, is_sysv_var_args, saved_gra_len, saved_vra_len, mod);
172172
173 const instructions = try isel.instructions.toOwnedSlice(gpa);173 try isel.instructions.shrinkToLen(gpa);
174 var mir: Mir = .{174 try isel.literals.shrinkToLen(gpa);
175 try isel.nav_relocs.shrinkToLen(gpa);
176 try isel.uav_relocs.shrinkToLen(gpa);
177 try isel.lazy_relocs.shrinkToLen(gpa);
178 try isel.global_relocs.shrinkToLen(gpa);
179 try isel.literal_relocs.shrinkToLen(gpa);
180
181 const instructions = isel.instructions.toOwnedSliceAssert();
182
183 return .{
175 .prologue = instructions[prologue..epilogue],184 .prologue = instructions[prologue..epilogue],
176 .body = instructions[0..prologue],185 .body = instructions[0..prologue],
177 .epilogue = instructions[epilogue..],186 .epilogue = instructions[epilogue..],
178 .literals = &.{},187 .literals = isel.literals.toOwnedSliceAssert(),
179 .nav_relocs = &.{},188 .nav_relocs = isel.nav_relocs.toOwnedSliceAssert(),
180 .uav_relocs = &.{},189 .uav_relocs = isel.uav_relocs.toOwnedSliceAssert(),
181 .lazy_relocs = &.{},190 .lazy_relocs = isel.lazy_relocs.toOwnedSliceAssert(),
182 .global_relocs = &.{},191 .global_relocs = isel.global_relocs.toOwnedSliceAssert(),
183 .literal_relocs = &.{},192 .literal_relocs = isel.literal_relocs.toOwnedSliceAssert(),
184 };193 };
185 errdefer mir.deinit(gpa);
186 mir.literals = try isel.literals.toOwnedSlice(gpa);
187 mir.nav_relocs = try isel.nav_relocs.toOwnedSlice(gpa);
188 mir.uav_relocs = try isel.uav_relocs.toOwnedSlice(gpa);
189 mir.lazy_relocs = try isel.lazy_relocs.toOwnedSlice(gpa);
190 mir.global_relocs = try isel.global_relocs.toOwnedSlice(gpa);
191 mir.literal_relocs = try isel.literal_relocs.toOwnedSlice(gpa);
192 return mir;
193}194}
194195
195test {196test {
src/codegen/sparc64/CodeGen.zig+4-5
...@@ -324,13 +324,12 @@ pub fn generate(...@@ -324,13 +324,12 @@ pub fn generate(
324 else => |e| return e,324 else => |e| return e,
325 };325 };
326326
327 var mir: Mir = .{327 try function.mir_extra.shrinkToLen(gpa);
328
329 return .{
328 .instructions = function.mir_instructions.toOwnedSlice(),330 .instructions = function.mir_instructions.toOwnedSlice(),
329 .extra = &.{}, // fallible, so populated after errdefer331 .extra = function.mir_extra.toOwnedSliceAssert(),
330 };332 };
331 errdefer mir.deinit(gpa);
332 mir.extra = try function.mir_extra.toOwnedSlice(gpa);
333 return mir;
334}333}
335334
336fn gen(self: *Self) !void {335fn gen(self: *Self) !void {
src/codegen/wasm/CodeGen.zig+6-7
...@@ -852,10 +852,13 @@ fn generateInner(cg: *CodeGen, any_returns: bool) InnerError!Mir {...@@ -852,10 +852,13 @@ fn generateInner(cg: *CodeGen, any_returns: bool) InnerError!Mir {
852 try cg.addTag(.end);852 try cg.addTag(.end);
853 try cg.addTag(.dbg_epilogue_begin);853 try cg.addTag(.dbg_epilogue_begin);
854854
855 var mir: Mir = .{855 try cg.mir_extra.shrinkToLen(cg.gpa);
856 try cg.mir_locals.shrinkToLen(cg.gpa);
857
858 return .{
856 .instructions = cg.mir_instructions.toOwnedSlice(),859 .instructions = cg.mir_instructions.toOwnedSlice(),
857 .extra = &.{}, // fallible so assigned after errdefer860 .extra = cg.mir_extra.toOwnedSliceAssert(),
858 .locals = &.{}, // fallible so assigned after errdefer861 .locals = cg.mir_locals.toOwnedSliceAssert(),
859 .prologue = if (cg.initial_stack_value == .none) .none else .{862 .prologue = if (cg.initial_stack_value == .none) .none else .{
860 .sp_local = cg.initial_stack_value.local.value,863 .sp_local = cg.initial_stack_value.local.value,
861 .flags = .{ .stack_alignment = cg.stack_alignment },864 .flags = .{ .stack_alignment = cg.stack_alignment },
...@@ -867,10 +870,6 @@ fn generateInner(cg: *CodeGen, any_returns: bool) InnerError!Mir {...@@ -867,10 +870,6 @@ fn generateInner(cg: *CodeGen, any_returns: bool) InnerError!Mir {
867 .func_tys = cg.mir_func_tys.move(),870 .func_tys = cg.mir_func_tys.move(),
868 .error_name_table_ref_count = cg.error_name_table_ref_count,871 .error_name_table_ref_count = cg.error_name_table_ref_count,
869 };872 };
870 errdefer mir.deinit(cg.gpa);
871 mir.extra = try cg.mir_extra.toOwnedSlice(cg.gpa);
872 mir.locals = try cg.mir_locals.toOwnedSlice(cg.gpa);
873 return mir;
874}873}
875874
876const CallWValues = struct {875const CallWValues = struct {
src/codegen/x86_64/CodeGen.zig+12-15
...@@ -998,22 +998,19 @@ pub fn generate(...@@ -998,22 +998,19 @@ pub fn generate(
998 } },998 } },
999 });999 });
10001000
1001 var mir: Mir = .{1001 try function.mir_extra.shrinkToLen(gpa);
1002 .instructions = .empty,1002 try function.mir_string_bytes.shrinkToLen(gpa);
1003 .extra = &.{},1003 try function.mir_locals.shrinkToLen(gpa);
1004 .string_bytes = &.{},1004 try function.mir_table.shrinkToLen(gpa);
1005 .locals = &.{},1005
1006 .table = &.{},1006 return .{
1007 .frame_locs = .empty,1007 .instructions = function.mir_instructions.toOwnedSlice(),
1008 .extra = function.mir_extra.toOwnedSliceAssert(),
1009 .string_bytes = function.mir_string_bytes.toOwnedSliceAssert(),
1010 .locals = function.mir_locals.toOwnedSliceAssert(),
1011 .table = function.mir_table.toOwnedSliceAssert(),
1012 .frame_locs = function.frame_locs.toOwnedSlice(),
1008 };1013 };
1009 errdefer mir.deinit(gpa);
1010 mir.instructions = function.mir_instructions.toOwnedSlice();
1011 mir.extra = try function.mir_extra.toOwnedSlice(gpa);
1012 mir.string_bytes = try function.mir_string_bytes.toOwnedSlice(gpa);
1013 mir.locals = try function.mir_locals.toOwnedSlice(gpa);
1014 mir.table = try function.mir_table.toOwnedSlice(gpa);
1015 mir.frame_locs = function.frame_locs.toOwnedSlice();
1016 return mir;
1017}1014}
10181015
1019pub fn getTmpMir(cg: *CodeGen) Mir {1016pub fn getTmpMir(cg: *CodeGen) Mir {
src/link.zig+9-8
...@@ -171,8 +171,8 @@ pub const Diags = struct {...@@ -171,8 +171,8 @@ pub const Diags = struct {
171 ) Allocator.Error!void {171 ) Allocator.Error!void {
172 const gpa = diags.gpa;172 const gpa = diags.gpa;
173173
174 var context_lines = std.array_list.Managed([]const u8).init(gpa);174 var context_lines: std.ArrayList([]const u8) = .empty;
175 defer context_lines.deinit();175 defer context_lines.deinit(gpa);
176176
177 var current_err: ?*Lld = null;177 var current_err: ?*Lld = null;
178 var lines = mem.splitSequence(u8, stderr, if (builtin.os.tag == .windows) "\r\n" else "\n");178 var lines = mem.splitSequence(u8, stderr, if (builtin.os.tag == .windows) "\r\n" else "\n");
...@@ -181,16 +181,17 @@ pub const Diags = struct {...@@ -181,16 +181,17 @@ pub const Diags = struct {
181 mem.eql(u8, line[0..prefix.len], prefix) and line[prefix.len] == ':')181 mem.eql(u8, line[0..prefix.len], prefix) and line[prefix.len] == ':')
182 {182 {
183 if (current_err) |err| {183 if (current_err) |err| {
184 err.context_lines = try context_lines.toOwnedSlice();184 err.context_lines = try context_lines.toOwnedSlice(gpa);
185 }185 }
186186
187 var split = mem.splitSequence(u8, line, "error: ");187 var split = mem.splitSequence(u8, line, "error: ");
188 _ = split.first();188 _ = split.first();
189189
190 try diags.lld.ensureUnusedCapacity(gpa, 1);
191
190 const duped_msg = try std.fmt.allocPrint(gpa, "{s}: {s}", .{ prefix, split.rest() });192 const duped_msg = try std.fmt.allocPrint(gpa, "{s}: {s}", .{ prefix, split.rest() });
191 errdefer gpa.free(duped_msg);
192193
193 current_err = try diags.lld.addOne(gpa);194 current_err = diags.lld.addOneAssumeCapacity();
194 current_err.?.* = .{ .msg = duped_msg };195 current_err.?.* = .{ .msg = duped_msg };
195 } else if (current_err != null) {196 } else if (current_err != null) {
196 const context_prefix = ">>> ";197 const context_prefix = ">>> ";
...@@ -200,14 +201,14 @@ pub const Diags = struct {...@@ -200,14 +201,14 @@ pub const Diags = struct {
200 }201 }
201202
202 if (trimmed.len > 0) {203 if (trimmed.len > 0) {
203 const duped_line = try gpa.dupe(u8, trimmed);204 try context_lines.ensureUnusedCapacity(gpa, 1);
204 try context_lines.append(duped_line);205 context_lines.appendAssumeCapacity(try gpa.dupe(u8, trimmed));
205 }206 }
206 }207 }
207 }208 }
208209
209 if (current_err) |err| {210 if (current_err) |err| {
210 err.context_lines = try context_lines.toOwnedSlice();211 err.context_lines = try context_lines.toOwnedSlice(gpa);
211 }212 }
212 }213 }
213214
src/link/Elf/Archive.zig+5-2
...@@ -107,9 +107,12 @@ pub fn parse(...@@ -107,9 +107,12 @@ pub fn parse(
107 try objects.append(gpa, object);107 try objects.append(gpa, object);
108 }108 }
109109
110 try objects.shrinkToLen(gpa);
111 try strtab.shrinkToLen(gpa);
112
110 return .{113 return .{
111 .objects = try objects.toOwnedSlice(gpa),114 .objects = objects.toOwnedSliceAssert(),
112 .strtab = try strtab.toOwnedSlice(gpa),115 .strtab = strtab.toOwnedSliceAssert(),
113 };116 };
114}117}
115118
src/link/Elf/SharedObject.zig+11-5
...@@ -314,15 +314,21 @@ pub fn parse(...@@ -314,15 +314,21 @@ pub fn parse(
314 header.sections = &.{};314 header.sections = &.{};
315 errdefer gpa.free(sections);315 errdefer gpa.free(sections);
316316
317 try strtab.shrinkToLen(gpa);
318 try nonlocal_esyms.shrinkToLen(gpa);
319 try nonlocal_versyms.shrinkToLen(gpa);
320 try nonlocal_symbols.shrinkToLen(gpa);
321 try verstrings.shrinkToLen(gpa);
322
317 return .{323 return .{
318 .sections = sections,324 .sections = sections,
319 .stat = header.stat,325 .stat = header.stat,
320 .soname_index = header.soname_index,326 .soname_index = header.soname_index,
321 .strtab = try strtab.toOwnedSlice(gpa),327 .strtab = strtab.toOwnedSliceAssert(),
322 .symtab = try nonlocal_esyms.toOwnedSlice(gpa),328 .symtab = nonlocal_esyms.toOwnedSliceAssert(),
323 .versyms = try nonlocal_versyms.toOwnedSlice(gpa),329 .versyms = nonlocal_versyms.toOwnedSliceAssert(),
324 .symbols = try nonlocal_symbols.toOwnedSlice(gpa),330 .symbols = nonlocal_symbols.toOwnedSliceAssert(),
325 .verstrings = try verstrings.toOwnedSlice(gpa),331 .verstrings = verstrings.toOwnedSliceAssert(),
326 };332 };
327}333}
328334
src/link/tapi/yaml.zig+6-8
...@@ -211,9 +211,8 @@ pub const Value = union(enum) {...@@ -211,9 +211,8 @@ pub const Value = union(enum) {
211 .float => return Value{ .float = math.lossyCast(f64, input) },211 .float => return Value{ .float = math.lossyCast(f64, input) },
212212
213 .@"struct" => |info| if (info.is_tuple) {213 .@"struct" => |info| if (info.is_tuple) {
214 var list = std.array_list.Managed(Value).init(arena);214 var list: std.ArrayList(Value) = try .initCapacity(arena);
215 errdefer list.deinit();215 defer list.deinit();
216 try list.ensureTotalCapacityPrecise(info.fields.len);
217216
218 inline for (info.fields) |field| {217 inline for (info.fields) |field| {
219 if (try encode(arena, @field(input, field.name))) |value| {218 if (try encode(arena, @field(input, field.name))) |value| {
...@@ -221,7 +220,7 @@ pub const Value = union(enum) {...@@ -221,7 +220,7 @@ pub const Value = union(enum) {
221 }220 }
222 }221 }
223222
224 return Value{ .list = try list.toOwnedSlice() };223 return Value{ .list = try list.toOwnedSlice(arena) };
225 } else {224 } else {
226 var map = Map.init(arena);225 var map = Map.init(arena);
227 errdefer map.deinit();226 errdefer map.deinit();
...@@ -262,9 +261,8 @@ pub const Value = union(enum) {...@@ -262,9 +261,8 @@ pub const Value = union(enum) {
262 return Value{ .string = try arena.dupe(u8, input) };261 return Value{ .string = try arena.dupe(u8, input) };
263 }262 }
264263
265 var list = std.array_list.Managed(Value).init(arena);264 var list: std.ArrayList(Value) = .initCapacity(input.len);
266 errdefer list.deinit();265 defer list.deinit(arena);
267 try list.ensureTotalCapacityPrecise(input.len);
268266
269 for (input) |elem| {267 for (input) |elem| {
270 if (try encode(arena, elem)) |value| {268 if (try encode(arena, elem)) |value| {
...@@ -275,7 +273,7 @@ pub const Value = union(enum) {...@@ -275,7 +273,7 @@ pub const Value = union(enum) {
275 }273 }
276 }274 }
277275
278 return Value{ .list = try list.toOwnedSlice() };276 return Value{ .list = try list.toOwnedSlice(arena) };
279 },277 },
280 else => {278 else => {
281 @compileError("Unhandled type: {s}" ++ @typeName(@TypeOf(input)));279 @compileError("Unhandled type: {s}" ++ @typeName(@TypeOf(input)));
tools/docgen.zig+20-15
...@@ -337,20 +337,20 @@ const Action = enum {...@@ -337,20 +337,20 @@ const Action = enum {
337 close,337 close,
338};338};
339339
340fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {340fn genToc(gpa: Allocator, tokenizer: *Tokenizer) !Toc {
341 var urls = std.StringHashMap(Token).init(allocator);341 var urls = std.StringHashMap(Token).init(gpa);
342 errdefer urls.deinit();342 errdefer urls.deinit();
343343
344 var header_stack_size: usize = 0;344 var header_stack_size: usize = 0;
345 var last_action: Action = .open;345 var last_action: Action = .open;
346 var last_columns: ?u8 = null;346 var last_columns: ?u8 = null;
347347
348 var toc_buf: Writer.Allocating = .init(allocator);348 var toc_buf: Writer.Allocating = .init(gpa);
349 defer toc_buf.deinit();349 defer toc_buf.deinit();
350350
351 const toc = &toc_buf.writer;351 const toc = &toc_buf.writer;
352352
353 var nodes = std.array_list.Managed(Node).init(allocator);353 var nodes = std.array_list.Managed(Node).init(gpa);
354 defer nodes.deinit();354 defer nodes.deinit();
355355
356 try toc.writeByte('\n');356 try toc.writeByte('\n');
...@@ -408,7 +408,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {...@@ -408,7 +408,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {
408408
409 header_stack_size += 1;409 header_stack_size += 1;
410410
411 const urlized = try urlize(allocator, content);411 const urlized = try urlize(gpa, content);
412 try nodes.append(Node{412 try nodes.append(Node{
413 .HeaderOpen = HeaderOpen{413 .HeaderOpen = HeaderOpen{
414 .name = content,414 .name = content,
...@@ -450,7 +450,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {...@@ -450,7 +450,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {
450 last_action = .close;450 last_action = .close;
451 }451 }
452 } else if (mem.eql(u8, tag_name, "see_also")) {452 } else if (mem.eql(u8, tag_name, "see_also")) {
453 var list = std.array_list.Managed(SeeAlsoItem).init(allocator);453 var list = std.array_list.Managed(SeeAlsoItem).init(gpa);
454 errdefer list.deinit();454 errdefer list.deinit();
455455
456 while (true) {456 while (true) {
...@@ -465,7 +465,8 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {...@@ -465,7 +465,8 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {
465 },465 },
466 .separator => {},466 .separator => {},
467 .bracket_close => {467 .bracket_close => {
468 try nodes.append(Node{ .SeeAlso = try list.toOwnedSlice() });468 try nodes.ensureUnusedCapacity(1);
469 nodes.appendAssumeCapacity(.{ .SeeAlso = try list.toOwnedSlice() });
469 break;470 break;
470 },471 },
471 else => return parseError(tokenizer, see_also_tok, "invalid see_also token", .{}),472 else => return parseError(tokenizer, see_also_tok, "invalid see_also token", .{}),
...@@ -491,7 +492,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {...@@ -491,7 +492,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {
491492
492 try nodes.append(Node{493 try nodes.append(Node{
493 .Link = Link{494 .Link = Link{
494 .url = try urlize(allocator, url_name),495 .url = try urlize(gpa, url_name),
495 .name = name,496 .name = name,
496 .token = name_tok,497 .token = name_tok,
497 },498 },
...@@ -592,9 +593,14 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {...@@ -592,9 +593,14 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {
592 }593 }
593 }594 }
594595
596 const nodes_slice = try nodes.toOwnedSlice();
597 errdefer gpa.free(nodes_slice);
598 const toc_slice = try toc_buf.toOwnedSlice();
599 errdefer gpa.free(toc_slice);
600
595 return .{601 return .{
596 .nodes = try nodes.toOwnedSlice(),602 .nodes = nodes_slice,
597 .toc = try toc_buf.toOwnedSlice(),603 .toc = toc_slice,
598 .urls = urls,604 .urls = urls,
599 };605 };
600}606}
...@@ -617,12 +623,11 @@ fn urlize(gpa: Allocator, input: []const u8) ![]u8 {...@@ -617,12 +623,11 @@ fn urlize(gpa: Allocator, input: []const u8) ![]u8 {
617 return try buf.toOwnedSlice(gpa);623 return try buf.toOwnedSlice(gpa);
618}624}
619625
620fn escapeHtml(allocator: Allocator, input: []const u8) ![]u8 {626fn escapeHtml(gpa: Allocator, input: []const u8) ![]u8 {
621 var buf = std.array_list.Managed(u8).init(allocator);627 var buf: std.Io.Writer.Allocating = .init(gpa);
622 defer buf.deinit();628 defer buf.deinit(gpa);
623629
624 const out = buf.writer();630 try writeEscaped(&buf.writer, input);
625 try writeEscaped(out, input);
626 return try buf.toOwnedSlice();631 return try buf.toOwnedSlice();
627}632}
628633