authorgravatar for mason@gamesbymason.comMason Remaley <mason@gamesbymason.com> 2026-07-20 17:14:44-07:00
committergravatar for mason@gamesbymason.comMason Remaley <mason@gamesbymason.com> 2026-09-26 12:35:38-07:00
loged70c643492c7c49057a72ff3e1981cb1ca81e57
tree0e297668f0c10968588f99b35ffa366bab8db149
parent07149649ce9201399233628d2dea61ebb061c430

Use arena for diagnostics and results


4 files changed, 909 insertions(+), 1027 deletions(-)

lib/std/zig/ErrorBundle.zig+2-2
......@@ -631,7 +631,7 @@ pub const Wip = struct {
631631 const err_loc = std.zig.findLineColumn(source, err_span.main);
632632
633633 try eb.addRootErrorMessage(.{
634 .msg = try eb.addString(err.msg.get(zoir)),
634 .msg = try eb.addString(err.msg.get(&zoir)),
635635 .src_loc = try eb.addSourceLocation(.{
636636 .src_path = try eb.addString(src_path),
637637 .span_start = err_span.start,
......@@ -661,7 +661,7 @@ pub const Wip = struct {
661661
662662 // This line can cause `wip.extra.items` to be resized.
663663 const note_index = @backingInt(try eb.addErrorMessage(.{
664 .msg = try eb.addString(note.msg.get(zoir)),
664 .msg = try eb.addString(note.msg.get(&zoir)),
665665 .src_loc = try eb.addSourceLocation(.{
666666 .src_path = try eb.addString(src_path),
667667 .span_start = note_span.start,
lib/std/zig/Zoir.zig+6-6
......@@ -42,7 +42,7 @@ pub const Header = extern struct {
4242 }
4343};
4444
45pub fn hasCompileErrors(zoir: Zoir) bool {
45pub fn hasCompileErrors(zoir: *const Zoir) bool {
4646 if (zoir.compile_errors.len > 0) {
4747 assert(zoir.nodes.len == 0);
4848 assert(zoir.extra.len == 0);
......@@ -54,7 +54,7 @@ pub fn hasCompileErrors(zoir: Zoir) bool {
5454 }
5555}
5656
57pub fn deinit(zoir: Zoir, gpa: Allocator) void {
57pub fn deinit(zoir: *const Zoir, gpa: Allocator) void {
5858 var nodes = zoir.nodes;
5959 nodes.deinit(gpa);
6060
......@@ -105,7 +105,7 @@ pub const Node = union(enum) {
105105 root = 0,
106106 _,
107107
108 pub fn get(idx: Index, zoir: Zoir) Node {
108 pub fn get(idx: Index, zoir: *const Zoir) Node {
109109 const repr = zoir.nodes.get(@backingInt(idx));
110110 return switch (repr.tag) {
111111 .true => .true,
......@@ -151,7 +151,7 @@ pub const Node = union(enum) {
151151 };
152152 }
153153
154 pub fn getAstNode(idx: Index, zoir: Zoir) std.zig.Ast.Node.Index {
154 pub fn getAstNode(idx: Index, zoir: *const Zoir) std.zig.Ast.Node.Index {
155155 return zoir.nodes.items(.ast_node)[@backingInt(idx)];
156156 }
157157
......@@ -227,7 +227,7 @@ pub const Node = union(enum) {
227227
228228pub const NullTerminatedString = enum(u32) {
229229 _,
230 pub fn get(nts: NullTerminatedString, zoir: Zoir) [:0]const u8 {
230 pub fn get(nts: NullTerminatedString, zoir: *const Zoir) [:0]const u8 {
231231 const idx = std.mem.findScalar(u8, zoir.string_bytes[@backingInt(nts)..], 0).?;
232232 return zoir.string_bytes[@backingInt(nts)..][0..idx :0];
233233 }
......@@ -244,7 +244,7 @@ pub const CompileError = extern struct {
244244 first_note: u32,
245245 note_count: u32,
246246
247 pub fn getNotes(err: CompileError, zoir: Zoir) []const Note {
247 pub fn getNotes(err: CompileError, zoir: *const Zoir) []const Note {
248248 return zoir.error_notes[err.first_note..][0..err.note_count];
249249 }
250250
lib/std/zig/ZonGen.zig+4-4
......@@ -490,7 +490,7 @@ fn appendIdentStr(zg: *ZonGen, ident_token: Ast.TokenIndex) error{ OutOfMemory,
490490}
491491
492492/// Estimates the size of a string node without parsing it.
493pub fn strLitSizeHint(tree: Ast, node: Ast.Node.Index) usize {
493pub fn strLitSizeHint(tree: *const Ast, node: Ast.Node.Index) usize {
494494 switch (tree.nodeTag(node)) {
495495 // Parsed string literals are typically around the size of the raw strings.
496496 .string_literal => {
......@@ -515,7 +515,7 @@ pub fn strLitSizeHint(tree: Ast, node: Ast.Node.Index) usize {
515515
516516/// Parses the given node as a string literal.
517517pub fn parseStrLit(
518 tree: Ast,
518 tree: *const Ast,
519519 node: Ast.Node.Index,
520520 writer: *Writer,
521521) Writer.Error!std.zig.string_literal.Result {
......@@ -559,12 +559,12 @@ fn strLitAsString(zg: *ZonGen, str_node: Ast.Node.Index) error{ OutOfMemory, Bad
559559 const gpa = zg.gpa;
560560 const string_bytes = &zg.string_bytes;
561561 const str_index: u32 = @intCast(zg.string_bytes.items.len);
562 const size_hint = strLitSizeHint(zg.tree, str_node);
562 const size_hint = strLitSizeHint(&zg.tree, str_node);
563563 try string_bytes.ensureUnusedCapacity(gpa, size_hint);
564564 const result = r: {
565565 var aw: Writer.Allocating = .fromArrayList(gpa, &zg.string_bytes);
566566 defer zg.string_bytes = aw.toArrayList();
567 break :r parseStrLit(zg.tree, str_node, &aw.writer) catch |err| switch (err) {
567 break :r parseStrLit(&zg.tree, str_node, &aw.writer) catch |err| switch (err) {
568568 error.WriteFailed => return error.OutOfMemory,
569569 };
570570 };
lib/std/zon/parse.zig+897-1015
......@@ -1,13 +1,11 @@
11//! The simplest way to parse ZON at runtime is to use `fromSlice`/`fromSliceAlloc`.
22//!
3//! Note that if you need to parse ZON at compile time, you may use `@import`.
4//!
53//! Parsing from individual Zoir nodes is also available:
64//! * `fromZoir`/`fromZoirAlloc`
75//!
8//! To update an existing values, see the `updateFrom*` variants.
9//!
10//! For lower level control over parsing, see `std.zig.Zoir`.
6//! To update an existing values, see the `updateFrom*` variants. To get human readable errors, use
7//! the `diag` option. For lower level control over parsing, see `std.zig.Zoir`. For importing ZON
8//! at compile time, use `@import`.
119
1210const std = @import("std");
1311const Allocator = std.mem.Allocator;
......@@ -20,235 +18,122 @@ const StrLitErr = std.zig.string_literal.Error;
2018const NumberLiteralError = std.zig.number_literal.Error;
2119const assert = std.debug.assert;
2220const ArrayList = std.ArrayList;
21const ArenaAllocator = std.heap.ArenaAllocator;
2322
2423/// Rename when adding or removing support for a type.
2524const valid_types = {};
2625
27pub const Error = union(enum) {
28 zoir: Zoir.CompileError,
29 type_check: Error.TypeCheckFailure,
30
31 pub const Note = union(enum) {
32 zoir: Zoir.CompileError.Note,
33 type_check: TypeCheckFailure.Note,
34
35 pub const Iterator = struct {
36 index: usize = 0,
37 err: Error,
38 diag: *const Diagnostics,
39
40 pub fn next(self: *@This()) ?Note {
41 switch (self.err) {
42 .zoir => |err| {
43 if (self.index >= err.note_count) return null;
44 const note = err.getNotes(self.diag.zoir)[self.index];
45 self.index += 1;
46 return .{ .zoir = note };
47 },
48 .type_check => |err| {
49 if (self.index >= err.getNoteCount()) return null;
50 const note = err.getNote(self.index);
51 self.index += 1;
52 return .{ .type_check = note };
53 },
54 }
55 }
56 };
57
58 fn formatMessage(self: []const u8, w: *std.Io.Writer) std.Io.Writer.Error!void {
59 // Just writes the string for now, but we're keeping this behind a formatter so we have
60 // the option to extend it in the future to print more advanced messages (like `Error`
61 // does) without breaking the API.
62 try w.writeAll(self);
63 }
64
65 pub fn fmtMessage(self: Note, diag: *const Diagnostics) std.fmt.Alt([]const u8, Note.formatMessage) {
66 return .{ .data = switch (self) {
67 .zoir => |note| note.msg.get(diag.zoir),
68 .type_check => |note| note.msg,
69 } };
70 }
71
72 pub fn getLocation(self: Note, diag: *const Diagnostics) Ast.Location {
73 switch (self) {
74 .zoir => |note| return zoirErrorLocation(diag.ast, note.token, note.node_or_offset),
75 .type_check => |note| return diag.ast.tokenLocation(note.offset, note.token),
76 }
77 }
26pub const Error = struct {
27 msg: []const u8,
28 loc: Ast.Location,
29 token: Ast.OptionalTokenIndex,
30 /// If `token == .none`, this is an `Ast.Node.Index`.
31 /// Otherwise, this is a byte offset into `token`.
32 node_or_offset: u32,
33 notes: []Note,
34
35 const InitOptions = struct {
36 msg: []const u8,
37 token: Ast.OptionalTokenIndex,
38 node_or_offset: u32,
39 notes: []Note,
7840 };
7941
80 pub const Iterator = struct {
81 index: usize = 0,
82 diag: *const Diagnostics,
83
84 pub fn next(self: *@This()) ?Error {
85 if (self.index < self.diag.zoir.compile_errors.len) {
86 const result: Error = .{ .zoir = self.diag.zoir.compile_errors[self.index] };
87 self.index += 1;
88 return result;
89 }
90
91 if (self.diag.type_check) |err| {
92 if (self.index == self.diag.zoir.compile_errors.len) {
93 const result: Error = .{ .type_check = err };
94 self.index += 1;
95 return result;
96 }
97 }
98
99 return null;
100 }
101 };
102
103 const TypeCheckFailure = struct {
104 const Note = struct {
105 token: Ast.TokenIndex,
106 offset: u32,
107 msg: []const u8,
108 owned: bool,
109
110 fn deinit(self: @This(), gpa: Allocator) void {
111 if (self.owned) gpa.free(self.msg);
112 }
42 fn init(ast: *const Ast, options: InitOptions) @This() {
43 return .{
44 .msg = options.msg,
45 .loc = astLoc(ast, options.token, options.node_or_offset),
46 .token = options.token,
47 .node_or_offset = options.node_or_offset,
48 .notes = options.notes,
11349 };
114
115 message: []const u8,
116 owned: bool,
117 token: Ast.TokenIndex,
118 offset: u32,
119 note: ?@This().Note,
120
121 fn deinit(self: @This(), gpa: Allocator) void {
122 if (self.note) |note| note.deinit(gpa);
123 if (self.owned) gpa.free(self.message);
124 }
125
126 fn getNoteCount(self: @This()) usize {
127 return @intFromBool(self.note != null);
128 }
129
130 fn getNote(self: @This(), index: usize) @This().Note {
131 assert(index == 0);
132 return self.note.?;
133 }
134 };
135
136 const FormatMessage = struct {
137 err: Error,
138 diag: *const Diagnostics,
139 };
140
141 fn formatMessage(self: FormatMessage, w: *std.Io.Writer) std.Io.Writer.Error!void {
142 switch (self.err) {
143 .zoir => |err| try w.writeAll(err.msg.get(self.diag.zoir)),
144 .type_check => |tc| try w.writeAll(tc.message),
145 }
146 }
147
148 pub fn fmtMessage(self: @This(), diag: *const Diagnostics) std.fmt.Alt(FormatMessage, formatMessage) {
149 return .{ .data = .{
150 .err = self,
151 .diag = diag,
152 } };
153 }
154
155 pub fn getLocation(self: @This(), diag: *const Diagnostics) Ast.Location {
156 return switch (self) {
157 .zoir => |err| return zoirErrorLocation(
158 diag.ast,
159 err.token,
160 err.node_or_offset,
161 ),
162 .type_check => |err| return diag.ast.tokenLocation(err.offset, err.token),
163 };
164 }
165
166 pub fn iterateNotes(self: @This(), diag: *const Diagnostics) Note.Iterator {
167 return .{ .err = self, .diag = diag };
16850 }
16951
170 fn zoirErrorLocation(ast: Ast, maybe_token: Ast.OptionalTokenIndex, node_or_offset: u32) Ast.Location {
52 fn astLoc(
53 ast: *const Ast,
54 maybe_token: Ast.OptionalTokenIndex,
55 node_or_offset: u32,
56 ) Ast.Location {
17157 if (maybe_token.unwrap()) |token| {
172 var location = ast.tokenLocation(0, token);
173 location.column += node_or_offset;
174 return location;
58 var loc = ast.tokenLocation(0, token);
59 loc.column += node_or_offset;
60 return loc;
17561 } else {
17662 const ast_node: Ast.Node.Index = @fromBackingInt(@intCast(node_or_offset));
17763 const token = ast.nodeMainToken(ast_node);
17864 return ast.tokenLocation(0, token);
17965 }
18066 }
67
68 pub const Note = struct {
69 msg: []const u8,
70 loc: Ast.Location,
71 token: Ast.OptionalTokenIndex,
72 /// If `token == .none`, this is an `Ast.Node.Index`.
73 /// Otherwise, this is a byte offset into `token`.
74 node_or_offset: u32,
75
76 const InitOptions = struct {
77 msg: []const u8,
78 token: Ast.OptionalTokenIndex,
79 node_or_offset: u32,
80 };
81
82 fn init(ast: *const Ast, options: @This().InitOptions) @This() {
83 return .{
84 .msg = options.msg,
85 .loc = astLoc(ast, options.token, options.node_or_offset),
86 .token = options.token,
87 .node_or_offset = options.node_or_offset,
88 };
89 }
90 };
18191};
18292
183/// Information about the success or failure of a parse.
93/// Human readable information about the success or failure of a parse.
18494pub const Diagnostics = struct {
185 ast: Ast = .{
186 .source = "",
187 .tokens = .empty,
188 .nodes = .empty,
189 .extra_data = &.{},
190 .mode = .zon,
191 .errors = &.{},
192 },
193 zoir: Zoir = .{
194 .nodes = .empty,
195 .extra = &.{},
196 .limbs = &.{},
197 .string_bytes = &.{},
198 .compile_errors = &.{},
199 .error_notes = &.{},
200 },
201 type_check: ?Error.TypeCheckFailure = null,
202
203 fn assertEmpty(self: Diagnostics) void {
204 assert(self.ast.tokens.len == 0);
205 assert(self.zoir.nodes.len == 0);
206 assert(self.type_check == null);
207 }
208
209 pub fn deinit(self: *Diagnostics, gpa: Allocator) void {
210 self.ast.deinit(gpa);
211 self.zoir.deinit(gpa);
212 if (self.type_check) |tc| tc.deinit(gpa);
213 self.* = undefined;
214 }
215
216 pub fn iterateErrors(self: *const Diagnostics) Error.Iterator {
217 return .{ .diag = self };
95 arena: Allocator,
96 compile_errors: std.ArrayList(Error),
97
98 pub fn init(arena: Allocator) @This() {
99 return .{
100 .arena = arena,
101 .compile_errors = .empty,
102 };
218103 }
219104
220105 pub fn format(self: *const @This(), w: *std.Io.Writer) std.Io.Writer.Error!void {
221 var errors = self.iterateErrors();
222 while (errors.next()) |err| {
223 const loc = err.getLocation(self);
224 const msg = err.fmtMessage(self);
225 try w.print("{d}:{d}: error: {f}\n", .{ loc.line + 1, loc.column + 1, msg });
226
227 var notes = err.iterateNotes(self);
228 while (notes.next()) |note| {
229 const note_loc = note.getLocation(self);
230 const note_msg = note.fmtMessage(self);
231 try w.print("{d}:{d}: note: {f}\n", .{
232 note_loc.line + 1,
233 note_loc.column + 1,
234 note_msg,
106 for (self.compile_errors.items) |e| {
107 try w.print("{d}:{d}: error: {s}\n", .{
108 e.loc.line + 1,
109 e.loc.column + 1,
110 e.msg,
111 });
112
113 for (e.notes) |note| {
114 try w.print("{d}:{d}: note: {s}\n", .{
115 note.loc.line + 1,
116 note.loc.column + 1,
117 note.msg,
235118 });
236119 }
237120 }
238121 }
122
123 pub fn clear(self: *@This()) void {
124 self.compile_errors.clearRetainingCapacity();
125 }
239126};
240127
241128pub const FromSliceOptions = struct {
129 /// Used for scratch allocations.
242130 gpa: Allocator,
131 /// The ZON source.
243132 source: [:0]const u8,
244133 /// Write human readable error messages here.
245134 diag: ?*Diagnostics,
246135 /// If true, unknown fields do not error.
247136 ignore_unknown_fields: bool = false,
248 /// If true, the parser cleans up partially parsed values on error. This requires some extra
249 /// bookkeeping, so you may want to turn it off if you don't need this feature (e.g. because
250 /// you're using arena allocation.)
251 free_on_error: bool = true,
252137};
253138
254139/// Parses the given slice as ZON.
......@@ -257,7 +142,7 @@ pub const FromSliceOptions = struct {
257142/// invalid or can not be deserialized into type `T`.
258143///
259144/// When the parser returns `error.ParseZon`, it will also store a human readable explanation in
260/// `diag` if non null. If diag is not null, it must be initialized to `.{}`.
145/// `diag` if non null.
261146///
262147/// Asserts at compile time that the result type doesn't contain pointers. As such, the result
263148/// doesn't need to be freed.
......@@ -265,25 +150,13 @@ pub const FromSliceOptions = struct {
265150/// An allocator is still required for temporary allocations made during parsing.
266151pub fn fromSlice(T: type, options: FromSliceOptions) error{ OutOfMemory, ParseZon }!T {
267152 comptime assert(!requiresAllocator(T));
268 return fromSliceAlloc(T, options);
269}
270
271pub fn UpdateFromSliceOptions(T: type) type {
272 return struct {
273 gpa: Allocator,
274 /// The value to update.
275 value: *T,
276 /// The ZON source.
277 source: [:0]const u8,
278 /// Write human readable error messages here.
279 diag: ?*Diagnostics,
280 /// If true, unknown fields do not error.
281 ignore_unknown_fields: bool = false,
282 /// If true, the old values of overriden fields are freed. You may want to turn this off if you
283 /// are updating a value that shouldn't be freed e.g. because it contains Zig string literals.
284 /// In this case, you can use arena allocation.
285 free_on_write: bool = true,
286 };
153 return fromSliceAlloc(T, .{
154 .gpa = options.gpa,
155 .arena = .failing,
156 .source = options.source,
157 .diag = options.diag,
158 .ignore_unknown_fields = options.ignore_unknown_fields,
159 });
287160}
288161
289162/// Similar to `fromSlice`, but updates an existing value `current`. Fields not specified by ZON are
......@@ -291,141 +164,139 @@ pub fn UpdateFromSliceOptions(T: type) type {
291164/// failure, values that were updated prior to the failure are left updated.
292165pub fn updateFromSlice(
293166 T: type,
294 options: UpdateFromSliceOptions(T),
167 value: *T,
168 options: FromSliceOptions,
295169) error{ OutOfMemory, ParseZon }!void {
296170 comptime assert(!requiresAllocator(T));
297 try updateFromSliceAlloc(T, options);
171 try updateFromSliceAlloc(T, value, .{
172 .gpa = options.gpa,
173 .arena = .failing,
174 .source = options.source,
175 .diag = options.diag,
176 .ignore_unknown_fields = options.ignore_unknown_fields,
177 });
298178}
299179
300pub const FromSliceAllocOptions = FromSliceOptions;
180pub const FromSliceAllocOptions = struct {
181 /// Used for scratch allocations.
182 gpa: Allocator,
183 /// Owns the result.
184 arena: Allocator,
185 /// The ZON source.
186 source: [:0]const u8,
187 /// Write human readable error messages here.
188 diag: ?*Diagnostics,
189 /// If true, unknown fields do not error.
190 ignore_unknown_fields: bool = false,
191};
301192
302193/// Like `fromSlice`, but the result may contain pointers. To automatically free the result, see
303194/// `free`.
304pub fn fromSliceAlloc(T: type, options: FromSliceOptions) error{ OutOfMemory, ParseZon }!T {
305 var result: T = undefined;
306 try parseSliceAlloc(T, &result, options.gpa, options.source, options.diag, .{
307 .ignore_unknown_fields = options.ignore_unknown_fields,
308 .ignore_missing_fields = false,
309 .free_on_error = options.free_on_error,
310 .free_on_write = false,
195pub fn fromSliceAlloc(T: type, options: FromSliceAllocOptions) error{ OutOfMemory, ParseZon }!T {
196 var value: T = undefined;
197 try parseSliceAlloc(T, &value, .{
198 .gpa = options.gpa,
199 .arena = options.arena,
200 .source = options.source,
201 .diag = options.diag,
202 .parser_options = .{
203 .ignore_unknown_fields = options.ignore_unknown_fields,
204 .ignore_missing_fields = false,
205 },
311206 });
312 return result;
207 return value;
313208}
314209
315pub const UpdateFromSliceAllocOptions = UpdateFromSliceOptions;
316
317210/// Like updateFromSlice`, but the result may contain pointers.
318211pub fn updateFromSliceAlloc(
319212 T: type,
320 options: UpdateFromSliceAllocOptions(T),
213 value: *T,
214 options: FromSliceAllocOptions,
321215) error{ OutOfMemory, ParseZon }!void {
322 try parseSliceAlloc(
323 T,
324 options.value,
325 options.gpa,
326 options.source,
327 options.diag,
328 .{
216 try parseSliceAlloc(T, value, .{
217 .gpa = options.gpa,
218 .arena = options.arena,
219 .source = options.source,
220 .diag = options.diag,
221 .parser_options = .{
329222 .ignore_unknown_fields = options.ignore_unknown_fields,
330223 .ignore_missing_fields = true,
331 .free_on_error = false,
332 .free_on_write = options.free_on_write,
333224 },
334 );
225 });
335226}
336227
337fn parseSliceAlloc(
338 T: type,
339 out: *T,
228const ParseSliceAllocOptions = struct {
340229 gpa: Allocator,
230 arena: Allocator,
341231 source: [:0]const u8,
342232 diag: ?*Diagnostics,
343 options: Parser.Options,
344) error{ OutOfMemory, ParseZon }!void {
345 if (diag) |s| s.assertEmpty();
233 parser_options: Parser.Options,
234};
346235
347 var ast = try std.zig.Ast.parse(gpa, source, .{ .mode = .zon });
348 defer if (diag == null) ast.deinit(gpa);
349 if (diag) |s| s.ast = ast;
236fn parseSliceAlloc(
237 T: type,
238 value: *T,
239 options: ParseSliceAllocOptions,
240) error{ OutOfMemory, ParseZon }!void {
241 var ast = try std.zig.Ast.parse(options.gpa, options.source, .{ .mode = .zon });
242 defer ast.deinit(options.gpa);
350243
351 // If there's no diagnostics, Zoir exists for the lifetime of this function. If there is a
352 // diagnostics, ownership is transferred to diagnostics.
353 var zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false });
354 defer if (diag == null) zoir.deinit(gpa);
244 var zoir = try ZonGen.generate(options.gpa, ast, .{ .parse_str_lits = false });
245 defer zoir.deinit(options.gpa);
355246
356 if (diag) |s| s.* = .{};
357 try parseZoirAlloc(T, out, gpa, ast, zoir, .root, diag, options);
247 try parseZoirAlloc(T, value, .{
248 .arena = options.arena,
249 .ast = &ast,
250 .zoir = &zoir,
251 .node = .root,
252 .diag = options.diag,
253 .parser_options = options.parser_options,
254 });
358255}
359256
360257pub const FromZoirOptions = struct {
361258 /// The AST for this this ZON value.
362 ast: Ast,
259 ast: *const Ast,
363260 /// The zig object intermediate representation of this ZON value.
364 zoir: Zoir,
261 zoir: *const Zoir,
365262 /// The node to start parsing at.
366263 node: Zoir.Node.Index = .root,
367264 /// Write human readable error messages here.
368265 diag: ?*Diagnostics,
369266 /// If true, unknown fields do not error.
370267 ignore_unknown_fields: bool = false,
371 /// If true, the parser cleans up partially parsed values on error. This requires some extra
372 /// bookkeeping, so you may want to turn it off if you don't need this feature (e.g. because
373 /// you're using arena allocation.)
374 free_on_error: bool = true,
375268};
376269
377270/// Like `fromSlice`, but operates on `Zoir` instead of ZON source.
378271pub fn fromZoir(T: type, options: FromZoirOptions) error{ParseZon}!T {
379272 comptime assert(!requiresAllocator(T));
380273 return fromZoirAlloc(T, .{
381 .gpa = .failing,
274 .arena = .failing,
382275 .ast = options.ast,
383276 .zoir = options.zoir,
384277 .node = options.node,
385278 .diag = options.diag,
386279 .ignore_unknown_fields = options.ignore_unknown_fields,
387 .free_on_error = options.free_on_error,
388280 }) catch |err| switch (err) {
389281 error.OutOfMemory => unreachable, // Checked by comptime assertion above
390282 else => |e| return e,
391283 };
392284}
393285
394pub fn UpdateFromZoirOptions(T: type) type {
395 return struct {
396 value: *T,
397 /// The AST for this ZON value.
398 ast: Ast,
399 /// The zig object intermediate representation of this ZON value.
400 zoir: Zoir,
401 /// The node to start parsing at.
402 node: Zoir.Node.Index = .root,
403 /// Write human readable error messages here.
404 diag: ?*Diagnostics,
405 /// If true, unknown fields do not error.
406 ignore_unknown_fields: bool = false,
407 /// If true, the old values of overriden fields are freed. You may want to turn this off if you
408 /// are updating a value that shouldn't be freed e.g. because it contains Zig string literals.
409 /// In this case, you can use arena allocation.
410 free_on_write: bool = true,
411 };
412}
413
414286/// Like `updateSlice`, but operates on `Zoir` instead of ZON source.
415287pub fn updateFromZoir(
416288 T: type,
417 options: UpdateFromZoirOptions(T),
289 value: *T,
290 options: FromZoirOptions,
418291) error{ParseZon}!void {
419292 comptime assert(!requiresAllocator(T));
420 updateFromZoirAlloc(T, .{
421 .gpa = .failing,
422 .value = options.value,
293 updateFromZoirAlloc(T, value, .{
294 .arena = .failing,
423295 .ast = options.ast,
424296 .zoir = options.zoir,
425297 .node = options.node,
426298 .diag = options.diag,
427299 .ignore_unknown_fields = options.ignore_unknown_fields,
428 .free_on_write = options.free_on_write,
429300 }) catch |err| switch (err) {
430301 error.OutOfMemory => unreachable, // Checked by comptime assertion above
431302 else => |e| return e,
......@@ -433,172 +304,103 @@ pub fn updateFromZoir(
433304}
434305
435306pub const FromZoirAllocOptions = struct {
436 gpa: Allocator,
307 /// Owns the result.
308 arena: Allocator,
437309 /// The AST for this ZON value.
438 ast: Ast,
310 ast: *const Ast,
439311 /// The zig object intermediate representation of this ZON value.
440 zoir: Zoir,
312 zoir: *const Zoir,
441313 /// The node to start parsing at.
442314 node: Zoir.Node.Index = .root,
443315 /// Write human readable error messages here.
444316 diag: ?*Diagnostics,
445317 /// If true, unknown fields do not error.
446318 ignore_unknown_fields: bool = false,
447 /// If true, the parser cleans up partially parsed values on error. This requires some extra
448 /// bookkeeping, so you may want to turn it off if you don't need this feature (e.g. because
449 /// you're using arena allocation.)
450 free_on_error: bool = true,
451319};
452320
453321/// Like `fromSliceAlloc`, but operates on `Zoir` instead of ZON source.
454322pub fn fromZoirAlloc(T: type, options: FromZoirAllocOptions) error{ OutOfMemory, ParseZon }!T {
455 var out: T = undefined;
456 try parseZoirAlloc(
457 T,
458 &out,
459 options.gpa,
460 options.ast,
461 options.zoir,
462 options.node,
463 options.diag,
464 .{
323 var value: T = undefined;
324 try parseZoirAlloc(T, &value, .{
325 .arena = options.arena,
326 .ast = options.ast,
327 .zoir = options.zoir,
328 .node = options.node,
329 .diag = options.diag,
330 .parser_options = .{
465331 .ignore_unknown_fields = options.ignore_unknown_fields,
466332 .ignore_missing_fields = false,
467 .free_on_error = options.free_on_error,
468 .free_on_write = false,
469333 },
470 );
471 return out;
472}
473
474pub fn UpdateFromZoirAllocOptions(T: type) type {
475 return struct {
476 gpa: Allocator,
477 value: *T,
478 ast: Ast,
479 zoir: Zoir,
480 node: Zoir.Node.Index = .root,
481 /// Write human readable error messages here.
482 diag: ?*Diagnostics,
483 /// If true, unknown fields do not error.
484 ignore_unknown_fields: bool = false,
485 /// If true, the old values of overriden fields are freed. You may want to turn this off if you
486 /// are updating a value that shouldn't be freed e.g. because it contains Zig string literals.
487 /// In this case, you can use arena allocation.
488 free_on_write: bool = true,
489 };
334 });
335 return value;
490336}
491337
492338/// Like updateSliceAlloc`, but operates on `Zoir` instead of ZON source.
493339pub fn updateFromZoirAlloc(
494340 T: type,
495 options: UpdateFromZoirAllocOptions(T),
341 value: *T,
342 options: FromZoirAllocOptions,
496343) error{ OutOfMemory, ParseZon }!void {
497 return parseZoirAlloc(
498 T,
499 options.value,
500 options.gpa,
501 options.ast,
502 options.zoir,
503 options.node,
504 options.diag,
505 .{
344 return parseZoirAlloc(T, value, .{
345 .arena = options.arena,
346 .ast = options.ast,
347 .zoir = options.zoir,
348 .node = options.node,
349 .diag = options.diag,
350 .parser_options = .{
506351 .ignore_unknown_fields = options.ignore_unknown_fields,
507352 .ignore_missing_fields = true,
508 .free_on_error = false,
509 .free_on_write = options.free_on_write,
510353 },
511 );
354 });
512355}
513356
514fn parseZoirAlloc(
515 T: type,
516 out: *T,
517 gpa: Allocator,
518 ast: Ast,
519 zoir: Zoir,
357const ParseZoirAllocOptions = struct {
358 arena: Allocator,
359 ast: *const Ast,
360 zoir: *const Zoir,
520361 node: Zoir.Node.Index,
521362 diag: ?*Diagnostics,
522 options: Parser.Options,
363 parser_options: Parser.Options,
364};
365
366fn parseZoirAlloc(
367 T: type,
368 value: *T,
369 options: ParseZoirAllocOptions,
523370) error{ OutOfMemory, ParseZon }!void {
524371 comptime assert(canParseType(T));
525372
526 if (diag) |s| {
527 s.assertEmpty();
528 s.ast = ast;
529 s.zoir = zoir;
530 }
531
532 if (zoir.hasCompileErrors()) {
373 if (options.zoir.hasCompileErrors()) {
374 if (options.diag) |s| {
375 for (options.zoir.compile_errors) |e| {
376 var notes: std.ArrayList(Error.Note) = .empty;
377 for (e.getNotes(options.zoir)) |note| {
378 try notes.append(s.arena, .init(options.ast, .{
379 .msg = try s.arena.dupe(u8, note.msg.get(options.zoir)),
380 .token = note.token,
381 .node_or_offset = note.node_or_offset,
382 }));
383 }
384 try s.compile_errors.append(s.arena, .init(options.ast, .{
385 .msg = try s.arena.dupe(u8, e.msg.get(options.zoir)),
386 .token = e.token,
387 .node_or_offset = e.node_or_offset,
388 .notes = try notes.toOwnedSlice(s.arena),
389 }));
390 }
391 }
533392 return error.ParseZon;
534393 }
535394
536395 var parser: Parser = .{
537 .gpa = gpa,
538 .ast = ast,
539 .zoir = zoir,
540 .options = options,
541 .diag = diag,
396 .arena = options.arena,
397 .ast = options.ast,
398 .zoir = options.zoir,
399 .options = options.parser_options,
400 .diag = options.diag,
542401 };
543402
544 try parser.parseExprInto(node, out);
545}
546
547/// Frees ZON values.
548///
549/// Provided for convenience, you may also free these values on your own using the same allocator
550/// passed into the parser.
551///
552/// Asserts at comptime that sufficient information is available via the type system to free this
553/// value. Untagged unions, for example, will fail this assert.
554pub fn free(gpa: Allocator, value: anytype) void {
555 const Value = @TypeOf(value);
556
557 _ = valid_types;
558 switch (@typeInfo(Value)) {
559 .bool, .int, .float, .@"enum" => {},
560 .pointer => |pointer| {
561 switch (pointer.size) {
562 .one => {
563 free(gpa, value.*);
564 gpa.destroy(value);
565 },
566 .slice => {
567 for (value) |item| {
568 free(gpa, item);
569 }
570 gpa.free(value);
571 },
572 .many, .c => comptime unreachable,
573 }
574 },
575 .array => {
576 freeArray(gpa, @TypeOf(value), &value);
577 },
578 .vector => |vector| {
579 const array: [vector.len]vector.child = value;
580 freeArray(gpa, @TypeOf(array), &array);
581 },
582 .@"struct" => |@"struct"| inline for (@"struct".field_names) |field_name| {
583 free(gpa, @field(value, field_name));
584 },
585 .@"union" => |@"union"| if (@"union".tag_type == null) {
586 if (comptime requiresAllocator(Value)) unreachable;
587 } else switch (value) {
588 inline else => |_, tag| {
589 free(gpa, @field(value, @tagName(tag)));
590 },
591 },
592 .optional => if (value) |some| {
593 free(gpa, some);
594 },
595 .void => {},
596 else => comptime unreachable,
597 }
598}
599
600fn freeArray(gpa: Allocator, comptime A: type, array: *const A) void {
601 for (array) |elem| free(gpa, elem);
403 try parser.parseExprInto(options.node, value);
602404}
603405
604406fn requiresAllocator(T: type) bool {
......@@ -623,17 +425,15 @@ fn requiresAllocator(T: type) bool {
623425}
624426
625427const Parser = struct {
626 gpa: Allocator,
627 ast: Ast,
628 zoir: Zoir,
428 arena: Allocator,
429 ast: *const Ast,
430 zoir: *const Zoir,
629431 diag: ?*Diagnostics,
630432 options: Parser.Options,
631433 pointer_depth: usize = 0,
632434
633435 pub const Options = struct {
634436 ignore_unknown_fields: bool,
635 free_on_error: bool,
636 free_on_write: bool,
637437 ignore_missing_fields: bool,
638438 };
639439
......@@ -654,37 +454,36 @@ const Parser = struct {
654454 out: anytype,
655455 ) ParseExprInnerError!void {
656456 if (@TypeOf(out.*) == Zoir.Node.Index) {
657 self.write(out, node);
457 out.* = node;
658458 return;
659459 }
660460
661461 switch (@typeInfo(@TypeOf(out.*))) {
662462 .optional => |optional| if (node.get(self.zoir) == .null) {
663 self.write(out, null);
463 out.* = null;
664464 } else {
665465 var new: optional.child = undefined;
666466 try self.parseExprInnerInto(node, &new);
667 self.write(out, new);
467 out.* = new;
668468 },
669 .bool => self.write(out, try self.parseBool(node)),
670 .int => self.write(out, try self.parseInt(@TypeOf(out.*), node)),
671 .float => self.write(out, try self.parseFloat(@TypeOf(out.*), node)),
672 .@"enum" => self.write(out, try self.parseEnumLiteral(@TypeOf(out.*), node)),
469 .bool => out.* = try self.parseBool(node),
470 .int => out.* = try self.parseInt(@TypeOf(out.*), node),
471 .float => out.* = try self.parseFloat(@TypeOf(out.*), node),
472 .@"enum" => out.* = try self.parseEnumLiteral(@TypeOf(out.*), node),
673473 .pointer => |pointer| switch (pointer.size) {
674474 .one => {
675 const slice = try self.gpa.alignedAlloc(
475 const slice = try self.arena.alignedAlloc(
676476 pointer.child,
677477 if (pointer.attrs.@"align") |a| .fromByteUnits(a) else null,
678478 1,
679479 );
680 errdefer self.gpa.free(slice);
681480 const new = &slice[0];
682481 {
683482 self.pointer_depth += 1;
684483 defer self.pointer_depth -= 1;
685484 try self.parseExprInnerInto(node, new);
686485 }
687 self.write(out, new);
486 out.* = new;
688487 },
689488 .slice => {
690489 const new = b: {
......@@ -693,7 +492,7 @@ const Parser = struct {
693492 const new = try self.parseSlicePointer(@TypeOf(out.*), node);
694493 break :b new;
695494 };
696 self.write(out, new);
495 out.* = new;
697496 },
698497 else => comptime unreachable,
699498 },
......@@ -867,7 +666,7 @@ const Parser = struct {
867666 var size_hint = ZonGen.strLitSizeHint(self.ast, ast_node);
868667 if (pointer.sentinel() != null) size_hint += 1;
869668
870 var aw: std.Io.Writer.Allocating = .init(self.gpa);
669 var aw: std.Io.Writer.Allocating = .init(self.arena);
871670 try aw.ensureUnusedCapacity(size_hint);
872671 defer aw.deinit();
873672 const result = ZonGen.parseStrLit(self.ast, ast_node, &aw.writer) catch return error.OutOfMemory;
......@@ -906,21 +705,15 @@ const Parser = struct {
906705 }
907706
908707 // Allocate the slice
909 const slice = try self.gpa.allocWithOptions(
708 const slice = try self.arena.allocWithOptions(
910709 pointer.child,
911710 nodes.len,
912711 .fromByteUnitsOptional(pointer.attrs.@"align"),
913712 pointer.sentinel(),
914713 );
915 errdefer self.gpa.free(slice);
916714
917715 // Parse the elements and return the slice
918716 for (slice, 0..) |*elem, i| {
919 errdefer if (self.options.free_on_error) {
920 for (slice[0..i]) |item| {
921 free(self.gpa, item);
922 }
923 };
924717 try self.parseExprInto(nodes.at(@intCast(i)), elem);
925718 }
926719
......@@ -953,13 +746,6 @@ const Parser = struct {
953746
954747 // Parse the elements and return the array
955748 inline for (out, 0..) |*elem, i| {
956 // If we fail to parse this field, free all fields before it
957 errdefer if (self.options.free_on_error) {
958 for (out[0..i]) |item| {
959 free(self.gpa, item);
960 }
961 };
962
963749 try self.parseExprInto(nodes.at(@intCast(i)), elem);
964750 }
965751
......@@ -972,7 +758,7 @@ const Parser = struct {
972758 const vector = @typeInfo(@TypeOf(out.*)).vector;
973759 var array: [vector.len]vector.child = undefined;
974760 try self.parseArrayInto(node, &array);
975 self.write(out, array);
761 out.* = array;
976762 }
977763
978764 fn parseStructInto(self: *@This(), node: Zoir.Node.Index, out: anytype) !void {
......@@ -998,22 +784,6 @@ const Parser = struct {
998784
999785 // Parse the struct
1000786 var field_found: [info.field_names.len]bool = @splat(false);
1001
1002 // If we fail partway through, free all already initialized fields
1003 var initialized: usize = 0;
1004 errdefer if (self.options.free_on_error and info.field_names.len > 0) {
1005 for (fields.names[0..initialized]) |name_runtime| {
1006 switch (field_indices.get(name_runtime.get(self.zoir)) orelse continue) {
1007 inline 0...(info.field_names.len - 1) => |name_index| {
1008 const name = info.field_names[name_index];
1009 free(self.gpa, @field(out, name));
1010 },
1011 else => unreachable, // Can't be out of bounds
1012 }
1013 }
1014 };
1015
1016 // Fill in the fields we found
1017787 for (0..fields.names.len) |i| {
1018788 const name = fields.names[i].get(self.zoir);
1019789 const field_index = field_indices.get(name) orelse {
......@@ -1040,8 +810,6 @@ const Parser = struct {
1040810 },
1041811 else => unreachable, // Can't be out of bounds
1042812 }
1043
1044 initialized += 1;
1045813 }
1046814
1047815 // Fill in any missing default fields
......@@ -1089,14 +857,6 @@ const Parser = struct {
1089857 return self.failNodeFmt(node, "missing tuple field with index {}", .{i});
1090858 }
1091859 } else {
1092 // If we fail to parse this field, free all fields before it
1093 errdefer if (self.options.free_on_error) {
1094 inline for (0..i) |j| {
1095 if (j >= i) break;
1096 free(self.gpa, out[j]);
1097 }
1098 };
1099
1100860 if (info.field_attrs[i].@"comptime") {
1101861 return self.failComptimeField(node, i);
1102862 } else {
......@@ -1144,7 +904,7 @@ const Parser = struct {
1144904 return self.failNode(node, "expected union");
1145905
1146906 // Instantiate the union
1147 self.write(out, @unionInit(@TypeOf(out.*), @"union".field_names[i], {}));
907 out.* = @unionInit(@TypeOf(out.*), @"union".field_names[i], {});
1148908 },
1149909 else => unreachable, // Can't be out of bounds
1150910 }
......@@ -1166,7 +926,7 @@ const Parser = struct {
1166926 if (@"union".field_types[i] == void) {
1167927 return self.failNode(field_val, "expected type 'void'");
1168928 } else {
1169 self.write(out, @unionInit(@TypeOf(out.*), @"union".field_names[i], undefined));
929 out.* = @unionInit(@TypeOf(out.*), @"union".field_names[i], undefined);
1170930 try self.parseExprInto(field_val, &@field(out.*, @"union".field_names[i]));
1171931 }
1172932 },
......@@ -1185,7 +945,7 @@ const Parser = struct {
1185945 args: anytype,
1186946 ) error{ OutOfMemory, ParseZon } {
1187947 @branchHint(.cold);
1188 return self.failTokenFmtNote(token, offset, fmt, args, null);
948 return self.failTokenFmtNote(token, offset, fmt, args, &.{});
1189949 }
1190950
1191951 fn failTokenFmtNote(
......@@ -1194,20 +954,16 @@ const Parser = struct {
1194954 offset: u32,
1195955 comptime fmt: []const u8,
1196956 args: anytype,
1197 note: ?Error.TypeCheckFailure.Note,
957 notes: []Error.Note,
1198958 ) error{ OutOfMemory, ParseZon } {
1199959 @branchHint(.cold);
1200960 comptime assert(args.len > 0);
1201 if (self.diag) |s| s.type_check = .{
1202 .token = token,
1203 .offset = offset,
1204 .message = std.fmt.allocPrint(self.gpa, fmt, args) catch |err| {
1205 if (note) |n| n.deinit(self.gpa);
1206 return err;
1207 },
1208 .owned = true,
1209 .note = note,
1210 };
961 if (self.diag) |s| try s.compile_errors.append(s.arena, .init(self.ast, .{
962 .token = .fromToken(token),
963 .node_or_offset = offset,
964 .msg = try std.fmt.allocPrint(s.arena, fmt, args),
965 .notes = notes,
966 }));
1211967 return error.ParseZon;
1212968 }
1213969
......@@ -1224,27 +980,26 @@ const Parser = struct {
1224980
1225981 fn failToken(
1226982 self: @This(),
1227 failure: Error.TypeCheckFailure,
1228 ) error{ParseZon} {
983 failure: Error,
984 ) error{ OutOfMemory, ParseZon } {
1229985 @branchHint(.cold);
1230 if (self.diag) |s| s.type_check = failure;
986 if (self.diag) |s| try s.compile_errors.append(s.arena, failure);
1231987 return error.ParseZon;
1232988 }
1233989
1234990 fn failNode(
1235991 self: @This(),
1236992 node: Zoir.Node.Index,
1237 message: []const u8,
1238 ) error{ParseZon} {
993 msg: []const u8,
994 ) error{ OutOfMemory, ParseZon } {
1239995 @branchHint(.cold);
1240996 const token = self.ast.nodeMainToken(node.getAstNode(self.zoir));
1241 return self.failToken(.{
1242 .token = token,
1243 .offset = 0,
1244 .message = message,
1245 .owned = false,
1246 .note = null,
1247 });
997 return self.failToken(.init(self.ast, .{
998 .token = .fromToken(token),
999 .node_or_offset = 0,
1000 .msg = msg,
1001 .notes = &.{},
1002 }));
12481003 }
12491004
12501005 fn failCannotRepresent(
......@@ -1265,8 +1020,7 @@ const Parser = struct {
12651020 name: []const u8,
12661021 ) error{ OutOfMemory, ParseZon } {
12671022 @branchHint(.cold);
1268 if (self.diag == null) return error.ParseZon;
1269 const gpa = self.gpa;
1023 const diag = self.diag orelse return error.ParseZon;
12701024 const token = if (field) |f| b: {
12711025 var buf: [2]Ast.Node.Index = undefined;
12721026 const struct_init = self.ast.fullStructInit(&buf, node.getAstNode(self.zoir)).?;
......@@ -1275,38 +1029,35 @@ const Parser = struct {
12751029 } else self.ast.nodeMainToken(node.getAstNode(self.zoir));
12761030 switch (@typeInfo(T)) {
12771031 inline .@"struct", .@"union", .@"enum" => |info| {
1278 const note: Error.TypeCheckFailure.Note = if (info.field_names.len == 0) b: {
1279 break :b .{
1280 .token = token,
1281 .offset = 0,
1032 var notes: std.ArrayList(Error.Note) = .empty;
1033 if (info.field_names.len == 0) {
1034 try notes.append(diag.arena, .init(self.ast, .{
1035 .token = .fromToken(token),
1036 .node_or_offset = 0,
12821037 .msg = "none expected",
1283 .owned = false,
1284 };
1285 } else b: {
1286 const msg = "supported: ";
1287 var buf: std.ArrayList(u8) = try .initCapacity(gpa, 64);
1288 defer buf.deinit(gpa);
1289 try buf.appendSlice(gpa, msg);
1038 }));
1039 } else {
1040 var aw: std.Io.Writer.Allocating = .init(diag.arena);
1041 aw.writer.writeAll("supported: ") catch return error.OutOfMemory;
12901042 inline for (info.field_names, 0..) |field_name, i| {
1291 if (i != 0) try buf.appendSlice(gpa, ", ");
1292 try buf.print(gpa, "'{f}'", .{std.zig.fmtIdFlags(field_name, .{
1043 if (i != 0) aw.writer.writeAll(", ") catch return error.OutOfMemory;
1044 aw.writer.print("'{f}'", .{std.zig.fmtIdFlags(field_name, .{
12931045 .allow_primitive = true,
12941046 .allow_underscore = true,
1295 })});
1047 })}) catch return error.OutOfMemory;
12961048 }
1297 break :b .{
1298 .token = token,
1299 .offset = 0,
1300 .msg = try buf.toOwnedSlice(gpa),
1301 .owned = true,
1302 };
1303 };
1049 try notes.append(diag.arena, .init(self.ast, .{
1050 .token = .fromToken(token),
1051 .node_or_offset = 0,
1052 .msg = try aw.toOwnedSlice(),
1053 }));
1054 }
13041055 return self.failTokenFmtNote(
13051056 token,
13061057 0,
13071058 "unexpected {s} '{s}'",
13081059 .{ item_kind, name },
1309 note,
1060 try notes.toOwnedSlice(diag.arena),
13101061 );
13111062 },
13121063 else => comptime unreachable,
......@@ -1333,23 +1084,12 @@ const Parser = struct {
13331084 const value_node = array_init.ast.elements[field];
13341085 break :b self.ast.firstToken(value_node);
13351086 };
1336 return self.failToken(.{
1337 .token = token,
1338 .offset = 0,
1339 .message = "cannot initialize comptime field",
1340 .owned = false,
1341 .note = null,
1342 });
1343 }
1344
1345 /// Write to out, freeing the old value first if necessary.
1346 fn write(self: *@This(), out: anytype, new: @TypeOf(out.*)) void {
1347 if (@typeInfo(@TypeOf(out)) == .pointer) {
1348 if (self.options.free_on_write and self.pointer_depth == 0) {
1349 free(self.gpa, out.*);
1350 }
1351 }
1352 out.* = new;
1087 return self.failToken(.init(self.ast, .{
1088 .token = .fromToken(token),
1089 .node_or_offset = 0,
1090 .msg = "cannot initialize comptime field",
1091 .notes = &.{},
1092 }));
13531093 }
13541094};
13551095
......@@ -1511,17 +1251,26 @@ test "std.zon requiresAllocator" {
15111251
15121252test "std.zon ast errors" {
15131253 const gpa = std.testing.allocator;
1514 var diag: Diagnostics = .{};
1515 defer diag.deinit(gpa);
1254 var arena_allocator: ArenaAllocator = .init(gpa);
1255 defer arena_allocator.deinit();
1256 const arena = arena_allocator.allocator();
1257 var diag: Diagnostics = .init(arena);
15161258 try std.testing.expectError(
15171259 error.ParseZon,
1518 fromSlice(struct {}, .{ .gpa = gpa, .source = ".{.x = 1 .y = 2}", .diag = &diag }),
1260 fromSlice(struct {}, .{
1261 .gpa = gpa,
1262 .source = ".{.x = 1 .y = 2}",
1263 .diag = &diag,
1264 }),
15191265 );
15201266 try std.testing.expectFmt("1:13: error: expected ',' after initializer\n", "{f}", .{diag});
15211267}
15221268
15231269test "std.zon comments" {
15241270 const gpa = std.testing.allocator;
1271 var arena_allocator: ArenaAllocator = .init(gpa);
1272 defer arena_allocator.deinit();
1273 const arena = arena_allocator.allocator();
15251274
15261275 try std.testing.expectEqual(@as(u8, 10), fromSlice(u8, .{
15271276 .gpa = gpa,
......@@ -1534,8 +1283,7 @@ test "std.zon comments" {
15341283 }));
15351284
15361285 {
1537 var diag: Diagnostics = .{};
1538 defer diag.deinit(gpa);
1286 var diag: Diagnostics = .init(arena);
15391287 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
15401288 .gpa = gpa,
15411289 .source =
......@@ -1555,10 +1303,13 @@ test "std.zon comments" {
15551303
15561304test "std.zon failure/oom formatting" {
15571305 const gpa = std.testing.allocator;
1558 var diag: Diagnostics = .{};
1559 defer diag.deinit(gpa);
1306 var arena_allocator: ArenaAllocator = .init(gpa);
1307 defer arena_allocator.deinit();
1308 const arena = arena_allocator.allocator();
1309 var diag: Diagnostics = .init(arena);
15601310 try std.testing.expectError(error.OutOfMemory, fromSliceAlloc([]const u8, .{
15611311 .gpa = .failing,
1312 .arena = arena,
15621313 .source = "\"foo\"",
15631314 .diag = &diag,
15641315 }));
......@@ -1566,10 +1317,11 @@ test "std.zon failure/oom formatting" {
15661317}
15671318
15681319test "std.zon fromSliceAlloc syntax error" {
1320 const gpa = std.testing.allocator;
15691321 try std.testing.expectError(
15701322 error.ParseZon,
15711323 fromSlice(u8, .{
1572 .gpa = std.testing.allocator,
1324 .gpa = gpa,
15731325 .source = ".{",
15741326 .diag = null,
15751327 }),
......@@ -1578,6 +1330,9 @@ test "std.zon fromSliceAlloc syntax error" {
15781330
15791331test "std.zon optional" {
15801332 const gpa = std.testing.allocator;
1333 var arena_allocator: ArenaAllocator = .init(gpa);
1334 defer arena_allocator.deinit();
1335 const arena = arena_allocator.allocator();
15811336
15821337 // Basic usage
15831338 {
......@@ -1599,22 +1354,26 @@ test "std.zon optional" {
15991354 {
16001355 const none = try fromSliceAlloc(?[]const u8, .{
16011356 .gpa = gpa,
1357 .arena = arena,
16021358 .source = "null",
16031359 .diag = null,
16041360 });
16051361 try std.testing.expect(none == null);
16061362 const some = try fromSliceAlloc(?[]const u8, .{
16071363 .gpa = gpa,
1364 .arena = arena,
16081365 .source = "\"foo\"",
16091366 .diag = null,
16101367 });
1611 defer free(gpa, some);
16121368 try std.testing.expectEqualStrings("foo", some.?);
16131369 }
16141370}
16151371
16161372test "std.zon unions" {
16171373 const gpa = std.testing.allocator;
1374 var arena_allocator: ArenaAllocator = .init(gpa);
1375 defer arena_allocator.deinit();
1376 const arena = arena_allocator.allocator();
16181377
16191378 // Unions
16201379 {
......@@ -1666,6 +1425,7 @@ test "std.zon unions" {
16661425
16671426 const noalloc = try fromSliceAlloc(Union, .{
16681427 .gpa = gpa,
1428 .arena = arena,
16691429 .source = ".{.baz = false}",
16701430 .diag = null,
16711431 });
......@@ -1673,21 +1433,25 @@ test "std.zon unions" {
16731433
16741434 const alloc = try fromSliceAlloc(Union, .{
16751435 .gpa = gpa,
1436 .arena = arena,
16761437 .source = ".{.bar = \"qux\"}",
16771438 .diag = null,
16781439 });
1679 defer free(gpa, alloc);
16801440 try std.testing.expectEqualDeep(Union{ .bar = "qux" }, alloc);
16811441 }
16821442
16831443 // Unknown field
16841444 {
16851445 const Union = union { x: f32, y: f32 };
1686 var diag: Diagnostics = .{};
1687 defer diag.deinit(gpa);
1446 var diag: Diagnostics = .init(arena);
16881447 try std.testing.expectError(
16891448 error.ParseZon,
1690 fromSliceAlloc(Union, .{ .gpa = gpa, .source = ".{.z=2.5}", .diag = &diag }),
1449 fromSliceAlloc(Union, .{
1450 .gpa = gpa,
1451 .arena = arena,
1452 .source = ".{.z=2.5}",
1453 .diag = &diag,
1454 }),
16911455 );
16921456 try std.testing.expectFmt(
16931457 \\1:4: error: unexpected field 'z'
......@@ -1702,11 +1466,15 @@ test "std.zon unions" {
17021466 // Explicit void field
17031467 {
17041468 const Union = union(enum) { x: void };
1705 var diag: Diagnostics = .{};
1706 defer diag.deinit(gpa);
1469 var diag: Diagnostics = .init(arena);
17071470 try std.testing.expectError(
17081471 error.ParseZon,
1709 fromSliceAlloc(Union, .{ .gpa = gpa, .source = ".{.x=1}", .diag = &diag }),
1472 fromSliceAlloc(Union, .{
1473 .gpa = gpa,
1474 .arena = arena,
1475 .source = ".{.x=1}",
1476 .diag = &diag,
1477 }),
17101478 );
17111479 try std.testing.expectFmt("1:6: error: expected type 'void'\n", "{f}", .{diag});
17121480 }
......@@ -1714,12 +1482,12 @@ test "std.zon unions" {
17141482 // Extra field
17151483 {
17161484 const Union = union { x: f32, y: bool };
1717 var diag: Diagnostics = .{};
1718 defer diag.deinit(gpa);
1485 var diag: Diagnostics = .init(arena);
17191486 try std.testing.expectError(
17201487 error.ParseZon,
17211488 fromSliceAlloc(Union, .{
17221489 .gpa = gpa,
1490 .arena = arena,
17231491 .source = ".{.x = 1.5, .y = true}",
17241492 .diag = &diag,
17251493 }),
......@@ -1730,11 +1498,15 @@ test "std.zon unions" {
17301498 // No fields
17311499 {
17321500 const Union = union { x: f32, y: bool };
1733 var diag: Diagnostics = .{};
1734 defer diag.deinit(gpa);
1501 var diag: Diagnostics = .init(arena);
17351502 try std.testing.expectError(
17361503 error.ParseZon,
1737 fromSliceAlloc(Union, .{ .gpa = gpa, .source = ".{}", .diag = &diag }),
1504 fromSliceAlloc(Union, .{
1505 .gpa = gpa,
1506 .arena = arena,
1507 .source = ".{}",
1508 .diag = &diag,
1509 }),
17381510 );
17391511 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});
17401512 }
......@@ -1742,10 +1514,10 @@ test "std.zon unions" {
17421514 // Enum literals cannot coerce into untagged unions
17431515 {
17441516 const Union = union { x: void };
1745 var diag: Diagnostics = .{};
1746 defer diag.deinit(gpa);
1517 var diag: Diagnostics = .init(arena);
17471518 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{
17481519 .gpa = gpa,
1520 .arena = arena,
17491521 .source = ".x",
17501522 .diag = &diag,
17511523 }));
......@@ -1755,10 +1527,10 @@ test "std.zon unions" {
17551527 // Unknown field for enum literal coercion
17561528 {
17571529 const Union = union(enum) { x: void };
1758 var diag: Diagnostics = .{};
1759 defer diag.deinit(gpa);
1530 var diag: Diagnostics = .init(arena);
17601531 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{
17611532 .gpa = gpa,
1533 .arena = arena,
17621534 .source = ".y",
17631535 .diag = &diag,
17641536 }));
......@@ -1775,10 +1547,10 @@ test "std.zon unions" {
17751547 // Non void field for enum literal coercion
17761548 {
17771549 const Union = union(enum) { x: f32 };
1778 var diag: Diagnostics = .{};
1779 defer diag.deinit(gpa);
1550 var diag: Diagnostics = .init(arena);
17801551 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{
17811552 .gpa = gpa,
1553 .arena = arena,
17821554 .source = ".x",
17831555 .diag = &diag,
17841556 }));
......@@ -1788,6 +1560,9 @@ test "std.zon unions" {
17881560
17891561test "std.zon structs" {
17901562 const gpa = std.testing.allocator;
1563 var arena_allocator: ArenaAllocator = .init(gpa);
1564 defer arena_allocator.deinit();
1565 const arena = arena_allocator.allocator();
17911566
17921567 // Structs (various sizes tested since they're parsed differently)
17931568 {
......@@ -1831,21 +1606,24 @@ test "std.zon structs" {
18311606
18321607 const parsed = try fromSliceAlloc(Foo, .{
18331608 .gpa = gpa,
1609 .arena = arena,
18341610 .source = ".{.bar = \"qux\", .baz = .{\"a\", \"b\"}}",
18351611 .diag = null,
18361612 });
1837 defer free(gpa, parsed);
18381613 try std.testing.expectEqualDeep(Foo{ .bar = "qux", .baz = &.{ "a", "b" } }, parsed);
18391614 }
18401615
18411616 // Unknown field
18421617 {
18431618 const Vec2 = struct { x: f32, y: f32 };
1844 var diag: Diagnostics = .{};
1845 defer diag.deinit(gpa);
1619 var diag: Diagnostics = .init(arena);
18461620 try std.testing.expectError(
18471621 error.ParseZon,
1848 fromSlice(Vec2, .{ .gpa = gpa, .source = ".{.x=1.5, .z=2.5}", .diag = &diag }),
1622 fromSlice(Vec2, .{
1623 .gpa = gpa,
1624 .source = ".{.x=1.5, .z=2.5}",
1625 .diag = &diag,
1626 }),
18491627 );
18501628 try std.testing.expectFmt(
18511629 \\1:12: error: unexpected field 'z'
......@@ -1860,11 +1638,14 @@ test "std.zon structs" {
18601638 // Duplicate field
18611639 {
18621640 const Vec2 = struct { x: f32, y: f32 };
1863 var diag: Diagnostics = .{};
1864 defer diag.deinit(gpa);
1641 var diag: Diagnostics = .init(arena);
18651642 try std.testing.expectError(
18661643 error.ParseZon,
1867 fromSlice(Vec2, .{ .gpa = gpa, .source = ".{.x=1.5, .x=2.5, .x=3.5}", .diag = &diag }),
1644 fromSlice(Vec2, .{
1645 .gpa = gpa,
1646 .source = ".{.x=1.5, .x=2.5, .x=3.5}",
1647 .diag = &diag,
1648 }),
18681649 );
18691650 try std.testing.expectFmt(
18701651 \\1:4: error: duplicate struct field name
......@@ -1888,11 +1669,14 @@ test "std.zon structs" {
18881669 // Unknown field when struct has no fields (regression test)
18891670 {
18901671 const Vec2 = struct {};
1891 var diag: Diagnostics = .{};
1892 defer diag.deinit(gpa);
1672 var diag: Diagnostics = .init(arena);
18931673 try std.testing.expectError(
18941674 error.ParseZon,
1895 fromSlice(Vec2, .{ .gpa = gpa, .source = ".{.x=1.5, .z=2.5}", .diag = &diag }),
1675 fromSlice(Vec2, .{
1676 .gpa = gpa,
1677 .source = ".{.x=1.5, .z=2.5}",
1678 .diag = &diag,
1679 }),
18961680 );
18971681 try std.testing.expectFmt(
18981682 \\1:4: error: unexpected field 'x'
......@@ -1904,11 +1688,14 @@ test "std.zon structs" {
19041688 // Missing field
19051689 {
19061690 const Vec2 = struct { x: f32, y: f32 };
1907 var diag: Diagnostics = .{};
1908 defer diag.deinit(gpa);
1691 var diag: Diagnostics = .init(arena);
19091692 try std.testing.expectError(
19101693 error.ParseZon,
1911 fromSlice(Vec2, .{ .gpa = gpa, .source = ".{.x=1.5}", .diag = &diag }),
1694 fromSlice(Vec2, .{
1695 .gpa = gpa,
1696 .source = ".{.x=1.5}",
1697 .diag = &diag,
1698 }),
19121699 );
19131700 try std.testing.expectFmt("1:2: error: missing required field y\n", "{f}", .{diag});
19141701 }
......@@ -1916,22 +1703,29 @@ test "std.zon structs" {
19161703 // Default field
19171704 {
19181705 const Vec2 = struct { x: f32, y: f32 = 1.5 };
1919 const parsed = try fromSlice(Vec2, .{ .gpa = gpa, .source = ".{.x = 1.2}", .diag = null });
1706 const parsed = try fromSlice(Vec2, .{
1707 .gpa = gpa,
1708 .source = ".{.x = 1.2}",
1709 .diag = null,
1710 });
19201711 try std.testing.expectEqual(Vec2{ .x = 1.2, .y = 1.5 }, parsed);
19211712 }
19221713
19231714 // Comptime field
19241715 {
19251716 const Vec2 = struct { x: f32, comptime y: f32 = 1.5 };
1926 const parsed = try fromSlice(Vec2, .{ .gpa = gpa, .source = ".{.x = 1.2}", .diag = null });
1717 const parsed = try fromSlice(Vec2, .{
1718 .gpa = gpa,
1719 .source = ".{.x = 1.2}",
1720 .diag = null,
1721 });
19271722 try std.testing.expectEqual(Vec2{ .x = 1.2, .y = 1.5 }, parsed);
19281723 }
19291724
19301725 // Comptime field assignment
19311726 {
19321727 const Vec2 = struct { x: f32, comptime y: f32 = 1.5 };
1933 var diag: Diagnostics = .{};
1934 defer diag.deinit(gpa);
1728 var diag: Diagnostics = .init(arena);
19351729 const parsed = fromSlice(Vec2, .{
19361730 .gpa = gpa,
19371731 .source = ".{.x = 1.2, .y = 1.5}",
......@@ -1971,8 +1765,7 @@ test "std.zon structs" {
19711765 {
19721766 // Structs
19731767 {
1974 var diag: Diagnostics = .{};
1975 defer diag.deinit(gpa);
1768 var diag: Diagnostics = .init(arena);
19761769 const parsed = fromSlice(struct {}, .{
19771770 .gpa = gpa,
19781771 .source = "Empty{}",
......@@ -1988,8 +1781,7 @@ test "std.zon structs" {
19881781
19891782 // Arrays
19901783 {
1991 var diag: Diagnostics = .{};
1992 defer diag.deinit(gpa);
1784 var diag: Diagnostics = .init(arena);
19931785 const parsed = fromSlice([3]u8, .{
19941786 .gpa = gpa,
19951787 .source = "[3]u8{1, 2, 3}",
......@@ -2005,10 +1797,10 @@ test "std.zon structs" {
20051797
20061798 // Slices
20071799 {
2008 var diag: Diagnostics = .{};
2009 defer diag.deinit(gpa);
1800 var diag: Diagnostics = .init(arena);
20101801 const parsed = fromSliceAlloc([]u8, .{
20111802 .gpa = gpa,
1803 .arena = arena,
20121804 .source = "[]u8{1, 2, 3}",
20131805 .diag = &diag,
20141806 });
......@@ -2022,8 +1814,7 @@ test "std.zon structs" {
20221814
20231815 // Tuples
20241816 {
2025 var diag: Diagnostics = .{};
2026 defer diag.deinit(gpa);
1817 var diag: Diagnostics = .init(arena);
20271818 const parsed = fromSlice(struct { u8, u8, u8 }, .{
20281819 .gpa = gpa,
20291820 .source = "Tuple{1, 2, 3}",
......@@ -2039,8 +1830,7 @@ test "std.zon structs" {
20391830
20401831 // Nested
20411832 {
2042 var diag: Diagnostics = .{};
2043 defer diag.deinit(gpa);
1833 var diag: Diagnostics = .init(arena);
20441834 const parsed = fromSlice(struct {}, .{
20451835 .gpa = gpa,
20461836 .source = ".{ .x = Tuple{1, 2, 3} }",
......@@ -2058,6 +1848,9 @@ test "std.zon structs" {
20581848
20591849test "std.zon tuples" {
20601850 const gpa = std.testing.allocator;
1851 var arena_allocator: ArenaAllocator = .init(gpa);
1852 defer arena_allocator.deinit();
1853 const arena = arena_allocator.allocator();
20611854
20621855 // Structs (various sizes tested since they're parsed differently)
20631856 {
......@@ -2100,21 +1893,24 @@ test "std.zon tuples" {
21001893 const Tuple = struct { []const u8, []const u8 };
21011894 const parsed = try fromSliceAlloc(Tuple, .{
21021895 .gpa = gpa,
1896 .arena = arena,
21031897 .source = ".{\"hello\", \"world\"}",
21041898 .diag = null,
21051899 });
2106 defer free(gpa, parsed);
21071900 try std.testing.expectEqualDeep(Tuple{ "hello", "world" }, parsed);
21081901 }
21091902
21101903 // Extra field
21111904 {
21121905 const Tuple = struct { f32, bool };
2113 var diag: Diagnostics = .{};
2114 defer diag.deinit(gpa);
1906 var diag: Diagnostics = .init(arena);
21151907 try std.testing.expectError(
21161908 error.ParseZon,
2117 fromSlice(Tuple, .{ .gpa = gpa, .source = ".{0.5, true, 123}", .diag = &diag }),
1909 fromSlice(Tuple, .{
1910 .gpa = gpa,
1911 .source = ".{0.5, true, 123}",
1912 .diag = &diag,
1913 }),
21181914 );
21191915 try std.testing.expectFmt("1:14: error: index 2 outside of tuple length 2\n", "{f}", .{diag});
21201916 }
......@@ -2122,11 +1918,14 @@ test "std.zon tuples" {
21221918 // Extra field
21231919 {
21241920 const Tuple = struct { f32, bool };
2125 var diag: Diagnostics = .{};
2126 defer diag.deinit(gpa);
1921 var diag: Diagnostics = .init(arena);
21271922 try std.testing.expectError(
21281923 error.ParseZon,
2129 fromSlice(Tuple, .{ .gpa = gpa, .source = ".{0.5}", .diag = &diag }),
1924 fromSlice(Tuple, .{
1925 .gpa = gpa,
1926 .source = ".{0.5}",
1927 .diag = &diag,
1928 }),
21301929 );
21311930 try std.testing.expectFmt(
21321931 "1:2: error: missing tuple field with index 1\n",
......@@ -2138,11 +1937,14 @@ test "std.zon tuples" {
21381937 // Tuple with unexpected field names
21391938 {
21401939 const Tuple = struct { f32 };
2141 var diag: Diagnostics = .{};
2142 defer diag.deinit(gpa);
1940 var diag: Diagnostics = .init(arena);
21431941 try std.testing.expectError(
21441942 error.ParseZon,
2145 fromSlice(Tuple, .{ .gpa = gpa, .source = ".{.foo = 10.0}", .diag = &diag }),
1943 fromSlice(Tuple, .{
1944 .gpa = gpa,
1945 .source = ".{.foo = 10.0}",
1946 .diag = &diag,
1947 }),
21461948 );
21471949 try std.testing.expectFmt("1:2: error: expected tuple\n", "{f}", .{diag});
21481950 }
......@@ -2150,11 +1952,14 @@ test "std.zon tuples" {
21501952 // Struct with missing field names
21511953 {
21521954 const Struct = struct { foo: f32 };
2153 var diag: Diagnostics = .{};
2154 defer diag.deinit(gpa);
1955 var diag: Diagnostics = .init(arena);
21551956 try std.testing.expectError(
21561957 error.ParseZon,
2157 fromSlice(Struct, .{ .gpa = gpa, .source = ".{10.0}", .diag = &diag }),
1958 fromSlice(Struct, .{
1959 .gpa = gpa,
1960 .source = ".{10.0}",
1961 .diag = &diag,
1962 }),
21581963 );
21591964 try std.testing.expectFmt("1:2: error: expected struct\n", "{f}", .{diag});
21601965 }
......@@ -2162,16 +1967,23 @@ test "std.zon tuples" {
21621967 // Comptime field
21631968 {
21641969 const Vec2 = struct { f32, comptime f32 = 1.5 };
2165 const parsed = try fromSlice(Vec2, .{ .gpa = gpa, .source = ".{ 1.2 }", .diag = null });
1970 const parsed = try fromSlice(Vec2, .{
1971 .gpa = gpa,
1972 .source = ".{ 1.2 }",
1973 .diag = null,
1974 });
21661975 try std.testing.expectEqual(Vec2{ 1.2, 1.5 }, parsed);
21671976 }
21681977
21691978 // Comptime field assignment
21701979 {
21711980 const Vec2 = struct { f32, comptime f32 = 1.5 };
2172 var diag: Diagnostics = .{};
2173 defer diag.deinit(gpa);
2174 const parsed = fromSlice(Vec2, .{ .gpa = gpa, .source = ".{ 1.2, 1.5}", .diag = &diag });
1981 var diag: Diagnostics = .init(arena);
1982 const parsed = fromSlice(Vec2, .{
1983 .gpa = gpa,
1984 .source = ".{ 1.2, 1.5}",
1985 .diag = &diag,
1986 });
21751987 try std.testing.expectError(error.ParseZon, parsed);
21761988 try std.testing.expectFmt(
21771989 \\1:9: error: cannot initialize comptime field
......@@ -2183,6 +1995,9 @@ test "std.zon tuples" {
21831995// Test sizes 0 to 3 since small sizes get parsed differently
21841996test "std.zon arrays and slices" {
21851997 const gpa = std.testing.allocator;
1998 var arena_allocator: ArenaAllocator = .init(gpa);
1999 defer arena_allocator.deinit();
2000 const arena = arena_allocator.allocator();
21862001
21872002 // Literals
21882003 {
......@@ -2236,50 +2051,50 @@ test "std.zon arrays and slices" {
22362051 {
22372052 const zero = try fromSliceAlloc([]const u8, .{
22382053 .gpa = gpa,
2054 .arena = arena,
22392055 .source = ".{}",
22402056 .diag = null,
22412057 });
2242 defer free(gpa, zero);
22432058 try std.testing.expectEqualSlices(u8, @as([]const u8, &.{}), zero);
22442059
22452060 const one = try fromSliceAlloc([]u8, .{
22462061 .gpa = gpa,
2062 .arena = arena,
22472063 .source = ".{'a'}",
22482064 .diag = null,
22492065 });
2250 defer free(gpa, one);
22512066 try std.testing.expectEqualSlices(u8, &.{'a'}, one);
22522067
22532068 const two = try fromSliceAlloc([]const u8, .{
22542069 .gpa = gpa,
2070 .arena = arena,
22552071 .source = ".{'a', 'b'}",
22562072 .diag = null,
22572073 });
2258 defer free(gpa, two);
22592074 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b' }, two);
22602075
22612076 const two_comma = try fromSliceAlloc([]const u8, .{
22622077 .gpa = gpa,
2078 .arena = arena,
22632079 .source = ".{'a', 'b',}",
22642080 .diag = null,
22652081 });
2266 defer free(gpa, two_comma);
22672082 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b' }, two_comma);
22682083
22692084 const three = try fromSliceAlloc([]u8, .{
22702085 .gpa = gpa,
2086 .arena = arena,
22712087 .source = ".{'a', 'b', 'c'}",
22722088 .diag = null,
22732089 });
2274 defer free(gpa, three);
22752090 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b', 'c' }, three);
22762091
22772092 const sentinel = try fromSliceAlloc([:'z']const u8, .{
22782093 .gpa = gpa,
2094 .arena = arena,
22792095 .source = ".{'a', 'b', 'c'}",
22802096 .diag = null,
22812097 });
2282 defer free(gpa, sentinel);
22832098 const expected_sentinel: [:'z']const u8 = &.{ 'a', 'b', 'c' };
22842099 try std.testing.expectEqualSlices(u8, expected_sentinel, sentinel);
22852100 }
......@@ -2291,10 +2106,10 @@ test "std.zon arrays and slices" {
22912106 {
22922107 const parsed = try fromSliceAlloc([1][]const u8, .{
22932108 .gpa = gpa,
2109 .arena = arena,
22942110 .source = ".{\"abc\"}",
22952111 .diag = null,
22962112 });
2297 defer free(gpa, parsed);
22982113 const expected: [1][]const u8 = .{"abc"};
22992114 try std.testing.expectEqualDeep(expected, parsed);
23002115 }
......@@ -2303,10 +2118,10 @@ test "std.zon arrays and slices" {
23032118 {
23042119 const parsed = try fromSliceAlloc([]const []const u8, .{
23052120 .gpa = gpa,
2121 .arena = arena,
23062122 .source = ".{\"abc\"}",
23072123 .diag = null,
23082124 });
2309 defer free(gpa, parsed);
23102125 const expected: []const []const u8 = &.{"abc"};
23112126 try std.testing.expectEqualDeep(expected, parsed);
23122127 }
......@@ -2330,10 +2145,10 @@ test "std.zon arrays and slices" {
23302145 {
23312146 const sentinel = try fromSliceAlloc([:2]align(4) u8, .{
23322147 .gpa = gpa,
2148 .arena = arena,
23332149 .source = ".{1}",
23342150 .diag = null,
23352151 });
2336 defer free(gpa, sentinel);
23372152 try std.testing.expectEqual(@as(usize, 1), sentinel.len);
23382153 try std.testing.expectEqual(@as(u8, 1), sentinel[0]);
23392154 try std.testing.expectEqual(@as(u8, 2), sentinel[1]);
......@@ -2342,11 +2157,14 @@ test "std.zon arrays and slices" {
23422157
23432158 // Expect 0 find 3
23442159 {
2345 var diag: Diagnostics = .{};
2346 defer diag.deinit(gpa);
2160 var diag: Diagnostics = .init(arena);
23472161 try std.testing.expectError(
23482162 error.ParseZon,
2349 fromSlice([0]u8, .{ .gpa = gpa, .source = ".{'a', 'b', 'c'}", .diag = &diag }),
2163 fromSlice([0]u8, .{
2164 .gpa = gpa,
2165 .source = ".{'a', 'b', 'c'}",
2166 .diag = &diag,
2167 }),
23502168 );
23512169 try std.testing.expectFmt(
23522170 "1:3: error: index 0 outside of array of length 0\n",
......@@ -2357,11 +2175,14 @@ test "std.zon arrays and slices" {
23572175
23582176 // Expect 1 find 2
23592177 {
2360 var diag: Diagnostics = .{};
2361 defer diag.deinit(gpa);
2178 var diag: Diagnostics = .init(arena);
23622179 try std.testing.expectError(
23632180 error.ParseZon,
2364 fromSlice([1]u8, .{ .gpa = gpa, .source = ".{'a', 'b'}", .diag = &diag }),
2181 fromSlice([1]u8, .{
2182 .gpa = gpa,
2183 .source = ".{'a', 'b'}",
2184 .diag = &diag,
2185 }),
23652186 );
23662187 try std.testing.expectFmt(
23672188 "1:8: error: index 1 outside of array of length 1\n",
......@@ -2372,11 +2193,14 @@ test "std.zon arrays and slices" {
23722193
23732194 // Expect 2 find 1
23742195 {
2375 var diag: Diagnostics = .{};
2376 defer diag.deinit(gpa);
2196 var diag: Diagnostics = .init(arena);
23772197 try std.testing.expectError(
23782198 error.ParseZon,
2379 fromSlice([2]u8, .{ .gpa = gpa, .source = ".{'a'}", .diag = &diag }),
2199 fromSlice([2]u8, .{
2200 .gpa = gpa,
2201 .source = ".{'a'}",
2202 .diag = &diag,
2203 }),
23802204 );
23812205 try std.testing.expectFmt(
23822206 "1:2: error: expected 2 array elements; found 1\n",
......@@ -2387,11 +2211,14 @@ test "std.zon arrays and slices" {
23872211
23882212 // Expect 3 find 0
23892213 {
2390 var diag: Diagnostics = .{};
2391 defer diag.deinit(gpa);
2214 var diag: Diagnostics = .init(arena);
23922215 try std.testing.expectError(
23932216 error.ParseZon,
2394 fromSlice([3]u8, .{ .gpa = gpa, .source = ".{}", .diag = &diag }),
2217 fromSlice([3]u8, .{
2218 .gpa = gpa,
2219 .source = ".{}",
2220 .diag = &diag,
2221 }),
23952222 );
23962223 try std.testing.expectFmt(
23972224 "1:2: error: expected 3 array elements; found 0\n",
......@@ -2404,23 +2231,26 @@ test "std.zon arrays and slices" {
24042231 {
24052232 // Array
24062233 {
2407 var diag: Diagnostics = .{};
2408 defer diag.deinit(gpa);
2234 var diag: Diagnostics = .init(arena);
24092235 try std.testing.expectError(
24102236 error.ParseZon,
2411 fromSlice([3]bool, .{ .gpa = gpa, .source = ".{'a', 'b', 'c'}", .diag = &diag }),
2237 fromSlice([3]bool, .{
2238 .gpa = gpa,
2239 .source = ".{'a', 'b', 'c'}",
2240 .diag = &diag,
2241 }),
24122242 );
24132243 try std.testing.expectFmt("1:3: error: expected type 'bool'\n", "{f}", .{diag});
24142244 }
24152245
24162246 // Slice
24172247 {
2418 var diag: Diagnostics = .{};
2419 defer diag.deinit(gpa);
2248 var diag: Diagnostics = .init(arena);
24202249 try std.testing.expectError(
24212250 error.ParseZon,
24222251 fromSliceAlloc([]bool, .{
24232252 .gpa = gpa,
2253 .arena = arena,
24242254 .source = ".{'a', 'b', 'c'}",
24252255 .diag = &diag,
24262256 }),
......@@ -2433,22 +2263,24 @@ test "std.zon arrays and slices" {
24332263 {
24342264 // Array
24352265 {
2436 var diag: Diagnostics = .{};
2437 defer diag.deinit(gpa);
2266 var diag: Diagnostics = .init(arena);
24382267 try std.testing.expectError(
24392268 error.ParseZon,
2440 fromSlice([3]u8, .{ .gpa = gpa, .source = "'a'", .diag = &diag }),
2269 fromSlice([3]u8, .{
2270 .gpa = gpa,
2271 .source = "'a'",
2272 .diag = &diag,
2273 }),
24412274 );
24422275 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
24432276 }
24442277
24452278 // Slice
24462279 {
2447 var diag: Diagnostics = .{};
2448 defer diag.deinit(gpa);
2280 var diag: Diagnostics = .init(arena);
24492281 try std.testing.expectError(
24502282 error.ParseZon,
2451 fromSliceAlloc([]u8, .{ .gpa = gpa, .source = "'a'", .diag = &diag }),
2283 fromSliceAlloc([]u8, .{ .gpa = gpa, .arena = arena, .source = "'a'", .diag = &diag }),
24522284 );
24532285 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
24542286 }
......@@ -2456,11 +2288,10 @@ test "std.zon arrays and slices" {
24562288
24572289 // Address of is not allowed (indirection for slices in ZON is implicit)
24582290 {
2459 var diag: Diagnostics = .{};
2460 defer diag.deinit(gpa);
2291 var diag: Diagnostics = .init(arena);
24612292 try std.testing.expectError(
24622293 error.ParseZon,
2463 fromSliceAlloc([]u8, .{ .gpa = gpa, .source = " &.{'a', 'b', 'c'}", .diag = &diag }),
2294 fromSliceAlloc([]u8, .{ .gpa = gpa, .arena = arena, .source = " &.{'a', 'b', 'c'}", .diag = &diag }),
24642295 );
24652296 try std.testing.expectFmt(
24662297 "1:3: error: pointers are not available in ZON\n",
......@@ -2472,15 +2303,18 @@ test "std.zon arrays and slices" {
24722303
24732304test "std.zon string literal" {
24742305 const gpa = std.testing.allocator;
2306 var arena_allocator: ArenaAllocator = .init(gpa);
2307 defer arena_allocator.deinit();
2308 const arena = arena_allocator.allocator();
24752309
24762310 // Basic string literal
24772311 {
24782312 const parsed = try fromSliceAlloc([]const u8, .{
24792313 .gpa = gpa,
2314 .arena = arena,
24802315 .source = "\"abc\"",
24812316 .diag = null,
24822317 });
2483 defer free(gpa, parsed);
24842318 try std.testing.expectEqualStrings(@as([]const u8, "abc"), parsed);
24852319 }
24862320
......@@ -2488,10 +2322,10 @@ test "std.zon string literal" {
24882322 {
24892323 const parsed = try fromSliceAlloc([]const u8, .{
24902324 .gpa = gpa,
2325 .arena = arena,
24912326 .source = "\"ab\\nc\"",
24922327 .diag = null,
24932328 });
2494 defer free(gpa, parsed);
24952329 try std.testing.expectEqualStrings(@as([]const u8, "ab\nc"), parsed);
24962330 }
24972331
......@@ -2499,31 +2333,29 @@ test "std.zon string literal" {
24992333 {
25002334 const parsed = try fromSliceAlloc([]const u8, .{
25012335 .gpa = gpa,
2336 .arena = arena,
25022337 .source = "\"ab\\x00c\"",
25032338 .diag = null,
25042339 });
2505 defer free(gpa, parsed);
25062340 try std.testing.expectEqualStrings(@as([]const u8, "ab\x00c"), parsed);
25072341 }
25082342
25092343 // Passing string literal to a mutable slice
25102344 {
25112345 {
2512 var diag: Diagnostics = .{};
2513 defer diag.deinit(gpa);
2346 var diag: Diagnostics = .init(arena);
25142347 try std.testing.expectError(
25152348 error.ParseZon,
2516 fromSliceAlloc([]u8, .{ .gpa = gpa, .source = "\"abcd\"", .diag = &diag }),
2349 fromSliceAlloc([]u8, .{ .gpa = gpa, .arena = arena, .source = "\"abcd\"", .diag = &diag }),
25172350 );
25182351 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
25192352 }
25202353
25212354 {
2522 var diag: Diagnostics = .{};
2523 defer diag.deinit(gpa);
2355 var diag: Diagnostics = .init(arena);
25242356 try std.testing.expectError(
25252357 error.ParseZon,
2526 fromSliceAlloc([]u8, .{ .gpa = gpa, .source = "\\\\abcd", .diag = &diag }),
2358 fromSliceAlloc([]u8, .{ .gpa = gpa, .arena = arena, .source = "\\\\abcd", .diag = &diag }),
25272359 );
25282360 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
25292361 }
......@@ -2536,21 +2368,27 @@ test "std.zon string literal" {
25362368 defer ast.deinit(gpa);
25372369 var zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false });
25382370 defer zoir.deinit(gpa);
2539 var diag: Diagnostics = .{};
2540 defer diag.deinit(gpa);
2371 var diag: Diagnostics = .init(arena);
25412372 try std.testing.expectError(
25422373 error.ParseZon,
2543 fromSlice([4:0]u8, .{ .gpa = gpa, .source = "\"abcd\"", .diag = &diag }),
2374 fromSlice([4:0]u8, .{
2375 .gpa = gpa,
2376 .source = "\"abcd\"",
2377 .diag = &diag,
2378 }),
25442379 );
25452380 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
25462381 }
25472382
25482383 {
2549 var diag: Diagnostics = .{};
2550 defer diag.deinit(gpa);
2384 var diag: Diagnostics = .init(arena);
25512385 try std.testing.expectError(
25522386 error.ParseZon,
2553 fromSlice([4:0]u8, .{ .gpa = gpa, .source = "\\\\abcd", .diag = &diag }),
2387 fromSlice([4:0]u8, .{
2388 .gpa = gpa,
2389 .source = "\\\\abcd",
2390 .diag = &diag,
2391 }),
25542392 );
25552393 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
25562394 }
......@@ -2561,10 +2399,10 @@ test "std.zon string literal" {
25612399 {
25622400 const parsed: [:0]const u8 = try fromSliceAlloc([:0]const u8, .{
25632401 .gpa = gpa,
2402 .arena = arena,
25642403 .source = "\"abc\"",
25652404 .diag = null,
25662405 });
2567 defer free(gpa, parsed);
25682406 try std.testing.expectEqualStrings("abc", parsed);
25692407 try std.testing.expectEqual(@as(u8, 0), parsed[3]);
25702408 }
......@@ -2572,10 +2410,10 @@ test "std.zon string literal" {
25722410 {
25732411 const parsed: [:0]const u8 = try fromSliceAlloc([:0]const u8, .{
25742412 .gpa = gpa,
2413 .arena = arena,
25752414 .source = "\\\\abc",
25762415 .diag = null,
25772416 });
2578 defer free(gpa, parsed);
25792417 try std.testing.expectEqualStrings("abc", parsed);
25802418 try std.testing.expectEqual(@as(u8, 0), parsed[3]);
25812419 }
......@@ -2584,21 +2422,19 @@ test "std.zon string literal" {
25842422 // Other value terminated slices
25852423 {
25862424 {
2587 var diag: Diagnostics = .{};
2588 defer diag.deinit(gpa);
2425 var diag: Diagnostics = .init(arena);
25892426 try std.testing.expectError(
25902427 error.ParseZon,
2591 fromSliceAlloc([:1]const u8, .{ .gpa = gpa, .source = "\"foo\"", .diag = &diag }),
2428 fromSliceAlloc([:1]const u8, .{ .gpa = gpa, .arena = arena, .source = "\"foo\"", .diag = &diag }),
25922429 );
25932430 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
25942431 }
25952432
25962433 {
2597 var diag: Diagnostics = .{};
2598 defer diag.deinit(gpa);
2434 var diag: Diagnostics = .init(arena);
25992435 try std.testing.expectError(
26002436 error.ParseZon,
2601 fromSliceAlloc([:1]const u8, .{ .gpa = gpa, .source = "\\\\foo", .diag = &diag }),
2437 fromSliceAlloc([:1]const u8, .{ .gpa = gpa, .arena = arena, .source = "\\\\foo", .diag = &diag }),
26022438 );
26032439 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
26042440 }
......@@ -2606,33 +2442,30 @@ test "std.zon string literal" {
26062442
26072443 // Expecting string literal, getting something else
26082444 {
2609 var diag: Diagnostics = .{};
2610 defer diag.deinit(gpa);
2445 var diag: Diagnostics = .init(arena);
26112446 try std.testing.expectError(
26122447 error.ParseZon,
2613 fromSliceAlloc([]const u8, .{ .gpa = gpa, .source = "true", .diag = &diag }),
2448 fromSliceAlloc([]const u8, .{ .gpa = gpa, .arena = arena, .source = "true", .diag = &diag }),
26142449 );
26152450 try std.testing.expectFmt("1:1: error: expected string\n", "{f}", .{diag});
26162451 }
26172452
26182453 // Expecting string literal, getting an incompatible tuple
26192454 {
2620 var diag: Diagnostics = .{};
2621 defer diag.deinit(gpa);
2455 var diag: Diagnostics = .init(arena);
26222456 try std.testing.expectError(
26232457 error.ParseZon,
2624 fromSliceAlloc([]const u8, .{ .gpa = gpa, .source = ".{false}", .diag = &diag }),
2458 fromSliceAlloc([]const u8, .{ .gpa = gpa, .arena = arena, .source = ".{false}", .diag = &diag }),
26252459 );
26262460 try std.testing.expectFmt("1:3: error: expected type 'u8'\n", "{f}", .{diag});
26272461 }
26282462
26292463 // Invalid string literal
26302464 {
2631 var diag: Diagnostics = .{};
2632 defer diag.deinit(gpa);
2465 var diag: Diagnostics = .init(arena);
26332466 try std.testing.expectError(
26342467 error.ParseZon,
2635 fromSliceAlloc([]const i8, .{ .gpa = gpa, .source = "\"\\a\"", .diag = &diag }),
2468 fromSliceAlloc([]const i8, .{ .gpa = gpa, .arena = arena, .source = "\"\\a\"", .diag = &diag }),
26362469 );
26372470 try std.testing.expectFmt("1:3: error: invalid escape character: 'a'\n", "{f}", .{diag});
26382471 }
......@@ -2640,21 +2473,19 @@ test "std.zon string literal" {
26402473 // Slice wrong child type
26412474 {
26422475 {
2643 var diag: Diagnostics = .{};
2644 defer diag.deinit(gpa);
2476 var diag: Diagnostics = .init(arena);
26452477 try std.testing.expectError(
26462478 error.ParseZon,
2647 fromSliceAlloc([]const i8, .{ .gpa = gpa, .source = "\"a\"", .diag = &diag }),
2479 fromSliceAlloc([]const i8, .{ .gpa = gpa, .arena = arena, .source = "\"a\"", .diag = &diag }),
26482480 );
26492481 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
26502482 }
26512483
26522484 {
2653 var diag: Diagnostics = .{};
2654 defer diag.deinit(gpa);
2485 var diag: Diagnostics = .init(arena);
26552486 try std.testing.expectError(
26562487 error.ParseZon,
2657 fromSliceAlloc([]const i8, .{ .gpa = gpa, .source = "\\\\a", .diag = &diag }),
2488 fromSliceAlloc([]const i8, .{ .gpa = gpa, .arena = arena, .source = "\\\\a", .diag = &diag }),
26582489 );
26592490 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
26602491 }
......@@ -2663,12 +2494,12 @@ test "std.zon string literal" {
26632494 // Bad alignment
26642495 {
26652496 {
2666 var diag: Diagnostics = .{};
2667 defer diag.deinit(gpa);
2497 var diag: Diagnostics = .init(arena);
26682498 try std.testing.expectError(
26692499 error.ParseZon,
26702500 fromSliceAlloc([]align(2) const u8, .{
26712501 .gpa = gpa,
2502 .arena = arena,
26722503 .source = "\"abc\"",
26732504 .diag = &diag,
26742505 }),
......@@ -2677,12 +2508,12 @@ test "std.zon string literal" {
26772508 }
26782509
26792510 {
2680 var diag: Diagnostics = .{};
2681 defer diag.deinit(gpa);
2511 var diag: Diagnostics = .init(arena);
26822512 try std.testing.expectError(
26832513 error.ParseZon,
26842514 fromSliceAlloc([]align(2) const u8, .{
26852515 .gpa = gpa,
2516 .arena = arena,
26862517 .source = "\\\\abc",
26872518 .diag = &diag,
26882519 }),
......@@ -2702,6 +2533,7 @@ test "std.zon string literal" {
27022533 };
27032534 const parsed = try fromSliceAlloc(S, .{
27042535 .gpa = gpa,
2536 .arena = arena,
27052537 .source =
27062538 \\.{
27072539 \\ .message =
......@@ -2722,7 +2554,6 @@ test "std.zon string literal" {
27222554 ,
27232555 .diag = null,
27242556 });
2725 defer free(gpa, parsed);
27262557 try std.testing.expectEqualStrings(
27272558 "hello, world!\nthis is a multiline string!\n\n...",
27282559 parsed.message,
......@@ -2735,6 +2566,9 @@ test "std.zon string literal" {
27352566
27362567test "std.zon enum literals" {
27372568 const gpa = std.testing.allocator;
2569 var arena_allocator: ArenaAllocator = .init(gpa);
2570 defer arena_allocator.deinit();
2571 const arena = arena_allocator.allocator();
27382572
27392573 const Enum = enum {
27402574 foo,
......@@ -2761,16 +2595,23 @@ test "std.zon enum literals" {
27612595 }));
27622596 try std.testing.expectEqual(
27632597 Enum.@"ab\nc",
2764 try fromSlice(Enum, .{ .gpa = gpa, .source = ".@\"ab\\nc\"", .diag = null }),
2598 try fromSlice(Enum, .{
2599 .gpa = gpa,
2600 .source = ".@\"ab\\nc\"",
2601 .diag = null,
2602 }),
27652603 );
27662604
27672605 // Bad tag
27682606 {
2769 var diag: Diagnostics = .{};
2770 defer diag.deinit(gpa);
2607 var diag: Diagnostics = .init(arena);
27712608 try std.testing.expectError(
27722609 error.ParseZon,
2773 fromSlice(Enum, .{ .gpa = gpa, .source = ".qux", .diag = &diag }),
2610 fromSlice(Enum, .{
2611 .gpa = gpa,
2612 .source = ".qux",
2613 .diag = &diag,
2614 }),
27742615 );
27752616 try std.testing.expectFmt(
27762617 \\1:2: error: unexpected enum literal 'qux'
......@@ -2784,11 +2625,14 @@ test "std.zon enum literals" {
27842625
27852626 // Bad tag that's too long for parser
27862627 {
2787 var diag: Diagnostics = .{};
2788 defer diag.deinit(gpa);
2628 var diag: Diagnostics = .init(arena);
27892629 try std.testing.expectError(
27902630 error.ParseZon,
2791 fromSlice(Enum, .{ .gpa = gpa, .source = ".@\"foobarbaz\"", .diag = &diag }),
2631 fromSlice(Enum, .{
2632 .gpa = gpa,
2633 .source = ".@\"foobarbaz\"",
2634 .diag = &diag,
2635 }),
27922636 );
27932637 try std.testing.expectFmt(
27942638 \\1:2: error: unexpected enum literal 'foobarbaz'
......@@ -2802,22 +2646,28 @@ test "std.zon enum literals" {
28022646
28032647 // Bad type
28042648 {
2805 var diag: Diagnostics = .{};
2806 defer diag.deinit(gpa);
2649 var diag: Diagnostics = .init(arena);
28072650 try std.testing.expectError(
28082651 error.ParseZon,
2809 fromSlice(Enum, .{ .gpa = gpa, .source = "true", .diag = &diag }),
2652 fromSlice(Enum, .{
2653 .gpa = gpa,
2654 .source = "true",
2655 .diag = &diag,
2656 }),
28102657 );
28112658 try std.testing.expectFmt("1:1: error: expected enum literal\n", "{f}", .{diag});
28122659 }
28132660
28142661 // Test embedded nulls in an identifier
28152662 {
2816 var diag: Diagnostics = .{};
2817 defer diag.deinit(gpa);
2663 var diag: Diagnostics = .init(arena);
28182664 try std.testing.expectError(
28192665 error.ParseZon,
2820 fromSlice(Enum, .{ .gpa = gpa, .source = ".@\"\\x00\"", .diag = &diag }),
2666 fromSlice(Enum, .{
2667 .gpa = gpa,
2668 .source = ".@\"\\x00\"",
2669 .diag = &diag,
2670 }),
28212671 );
28222672 try std.testing.expectFmt(
28232673 "1:2: error: identifier cannot contain null bytes\n",
......@@ -2829,6 +2679,9 @@ test "std.zon enum literals" {
28292679
28302680test "std.zon parse bool" {
28312681 const gpa = std.testing.allocator;
2682 var arena_allocator: ArenaAllocator = .init(gpa);
2683 defer arena_allocator.deinit();
2684 const arena = arena_allocator.allocator();
28322685
28332686 // Correct bools
28342687 try std.testing.expectEqual(true, try fromSlice(bool, .{
......@@ -2844,11 +2697,14 @@ test "std.zon parse bool" {
28442697
28452698 // Errors
28462699 {
2847 var diag: Diagnostics = .{};
2848 defer diag.deinit(gpa);
2700 var diag: Diagnostics = .init(arena);
28492701 try std.testing.expectError(
28502702 error.ParseZon,
2851 fromSlice(bool, .{ .gpa = gpa, .source = " foo", .diag = &diag }),
2703 fromSlice(bool, .{
2704 .gpa = gpa,
2705 .source = " foo",
2706 .diag = &diag,
2707 }),
28522708 );
28532709 try std.testing.expectFmt(
28542710 \\1:2: error: invalid expression
......@@ -2858,8 +2714,7 @@ test "std.zon parse bool" {
28582714 , "{f}", .{diag});
28592715 }
28602716 {
2861 var diag: Diagnostics = .{};
2862 defer diag.deinit(gpa);
2717 var diag: Diagnostics = .init(arena);
28632718 try std.testing.expectError(error.ParseZon, fromSlice(bool, .{
28642719 .gpa = gpa,
28652720 .source = "123",
......@@ -2893,6 +2748,9 @@ test "std.zon intFromFloatExact" {
28932748
28942749test "std.zon parse int" {
28952750 const gpa = std.testing.allocator;
2751 var arena_allocator: ArenaAllocator = .init(gpa);
2752 defer arena_allocator.deinit();
2753 const arena = arena_allocator.allocator();
28962754
28972755 // Test various numbers and types
28982756 try std.testing.expectEqual(@as(u8, 10), try fromSlice(u8, .{
......@@ -2984,8 +2842,7 @@ test "std.zon parse int" {
29842842 }),
29852843 );
29862844 {
2987 var diag: Diagnostics = .{};
2988 defer diag.deinit(gpa);
2845 var diag: Diagnostics = .init(arena);
29892846 try std.testing.expectError(error.ParseZon, fromSlice(i66, .{
29902847 .gpa = gpa,
29912848 .source = "36893488147419103232",
......@@ -2998,8 +2855,7 @@ test "std.zon parse int" {
29982855 );
29992856 }
30002857 {
3001 var diag: Diagnostics = .{};
3002 defer diag.deinit(gpa);
2858 var diag: Diagnostics = .init(arena);
30032859 try std.testing.expectError(error.ParseZon, fromSlice(i66, .{
30042860 .gpa = gpa,
30052861 .source = "-36893488147419103233",
......@@ -3105,8 +2961,7 @@ test "std.zon parse int" {
31052961
31062962 // Number with invalid character in the middle
31072963 {
3108 var diag: Diagnostics = .{};
3109 defer diag.deinit(gpa);
2964 var diag: Diagnostics = .init(arena);
31102965 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
31112966 .gpa = gpa,
31122967 .source = "32a32",
......@@ -3121,8 +2976,7 @@ test "std.zon parse int" {
31212976
31222977 // Failing to parse as int
31232978 {
3124 var diag: Diagnostics = .{};
3125 defer diag.deinit(gpa);
2979 var diag: Diagnostics = .init(arena);
31262980 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
31272981 .gpa = gpa,
31282982 .source = "true",
......@@ -3133,8 +2987,7 @@ test "std.zon parse int" {
31332987
31342988 // Failing because an int is out of range
31352989 {
3136 var diag: Diagnostics = .{};
3137 defer diag.deinit(gpa);
2990 var diag: Diagnostics = .init(arena);
31382991 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
31392992 .gpa = gpa,
31402993 .source = "256",
......@@ -3149,8 +3002,7 @@ test "std.zon parse int" {
31493002
31503003 // Failing because a negative int is out of range
31513004 {
3152 var diag: Diagnostics = .{};
3153 defer diag.deinit(gpa);
3005 var diag: Diagnostics = .init(arena);
31543006 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
31553007 .gpa = gpa,
31563008 .source = "-129",
......@@ -3165,8 +3017,7 @@ test "std.zon parse int" {
31653017
31663018 // Failing because an unsigned int is negative
31673019 {
3168 var diag: Diagnostics = .{};
3169 defer diag.deinit(gpa);
3020 var diag: Diagnostics = .init(arena);
31703021 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
31713022 .gpa = gpa,
31723023 .source = "-1",
......@@ -3181,8 +3032,7 @@ test "std.zon parse int" {
31813032
31823033 // Failing because a float is non-whole
31833034 {
3184 var diag: Diagnostics = .{};
3185 defer diag.deinit(gpa);
3035 var diag: Diagnostics = .init(arena);
31863036 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
31873037 .gpa = gpa,
31883038 .source = "1.5",
......@@ -3197,8 +3047,7 @@ test "std.zon parse int" {
31973047
31983048 // Failing because a float is negative
31993049 {
3200 var diag: Diagnostics = .{};
3201 defer diag.deinit(gpa);
3050 var diag: Diagnostics = .init(arena);
32023051 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
32033052 .gpa = gpa,
32043053 .source = "-1.0",
......@@ -3213,8 +3062,7 @@ test "std.zon parse int" {
32133062
32143063 // Negative integer zero
32153064 {
3216 var diag: Diagnostics = .{};
3217 defer diag.deinit(gpa);
3065 var diag: Diagnostics = .init(arena);
32183066 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
32193067 .gpa = gpa,
32203068 .source = "-0",
......@@ -3230,8 +3078,7 @@ test "std.zon parse int" {
32303078
32313079 // Negative integer zero casted to float
32323080 {
3233 var diag: Diagnostics = .{};
3234 defer diag.deinit(gpa);
3081 var diag: Diagnostics = .init(arena);
32353082 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{
32363083 .gpa = gpa,
32373084 .source = "-0",
......@@ -3261,8 +3108,7 @@ test "std.zon parse int" {
32613108
32623109 // Double negation is not allowed
32633110 {
3264 var diag: Diagnostics = .{};
3265 defer diag.deinit(gpa);
3111 var diag: Diagnostics = .init(arena);
32663112 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
32673113 .gpa = gpa,
32683114 .source = "--2",
......@@ -3276,11 +3122,14 @@ test "std.zon parse int" {
32763122 }
32773123
32783124 {
3279 var diag: Diagnostics = .{};
3280 defer diag.deinit(gpa);
3125 var diag: Diagnostics = .init(arena);
32813126 try std.testing.expectError(
32823127 error.ParseZon,
3283 fromSlice(f32, .{ .gpa = gpa, .source = "--2.0", .diag = &diag }),
3128 fromSlice(f32, .{
3129 .gpa = gpa,
3130 .source = "--2.0",
3131 .diag = &diag,
3132 }),
32843133 );
32853134 try std.testing.expectFmt(
32863135 "1:1: error: expected number or 'inf' after '-'\n",
......@@ -3291,8 +3140,7 @@ test "std.zon parse int" {
32913140
32923141 // Invalid int literal
32933142 {
3294 var diag: Diagnostics = .{};
3295 defer diag.deinit(gpa);
3143 var diag: Diagnostics = .init(arena);
32963144 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
32973145 .gpa = gpa,
32983146 .source = "0xg",
......@@ -3303,8 +3151,7 @@ test "std.zon parse int" {
33033151
33043152 // Notes on invalid int literal
33053153 {
3306 var diag: Diagnostics = .{};
3307 defer diag.deinit(gpa);
3154 var diag: Diagnostics = .init(arena);
33083155 try std.testing.expectError(error.ParseZon, fromSlice(u8, .{
33093156 .gpa = gpa,
33103157 .source = "0123",
......@@ -3320,10 +3167,12 @@ test "std.zon parse int" {
33203167
33213168test "std.zon negative char" {
33223169 const gpa = std.testing.allocator;
3170 var arena_allocator: ArenaAllocator = .init(gpa);
3171 defer arena_allocator.deinit();
3172 const arena = arena_allocator.allocator();
33233173
33243174 {
3325 var diag: Diagnostics = .{};
3326 defer diag.deinit(gpa);
3175 var diag: Diagnostics = .init(arena);
33273176 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{
33283177 .gpa = gpa,
33293178 .source = "-'a'",
......@@ -3336,8 +3185,7 @@ test "std.zon negative char" {
33363185 );
33373186 }
33383187 {
3339 var diag: Diagnostics = .{};
3340 defer diag.deinit(gpa);
3188 var diag: Diagnostics = .init(arena);
33413189 try std.testing.expectError(error.ParseZon, fromSlice(i16, .{
33423190 .gpa = gpa,
33433191 .source = "-'a'",
......@@ -3353,6 +3201,9 @@ test "std.zon negative char" {
33533201
33543202test "std.zon parse float" {
33553203 const gpa = std.testing.allocator;
3204 var arena_allocator: ArenaAllocator = .init(gpa);
3205 defer arena_allocator.deinit();
3206 const arena = arena_allocator.allocator();
33563207
33573208 // Test decimals
33583209 try std.testing.expectEqual(@as(f16, 0.5), try fromSlice(f16, .{
......@@ -3362,11 +3213,19 @@ test "std.zon parse float" {
33623213 }));
33633214 try std.testing.expectEqual(
33643215 @as(f32, 123.456),
3365 try fromSlice(f32, .{ .gpa = gpa, .source = "123.456", .diag = null }),
3216 try fromSlice(f32, .{
3217 .gpa = gpa,
3218 .source = "123.456",
3219 .diag = null,
3220 }),
33663221 );
33673222 try std.testing.expectEqual(
33683223 @as(f64, -123.456),
3369 try fromSlice(f64, .{ .gpa = gpa, .source = "-123.456", .diag = null }),
3224 try fromSlice(f64, .{
3225 .gpa = gpa,
3226 .source = "-123.456",
3227 .diag = null,
3228 }),
33703229 );
33713230 try std.testing.expectEqual(@as(f128, 42.5), try fromSlice(f128, .{
33723231 .gpa = gpa,
......@@ -3491,8 +3350,7 @@ test "std.zon parse float" {
34913350
34923351 // Negative nan not allowed
34933352 {
3494 var diag: Diagnostics = .{};
3495 defer diag.deinit(gpa);
3353 var diag: Diagnostics = .init(arena);
34963354 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{
34973355 .gpa = gpa,
34983356 .source = "-nan",
......@@ -3507,8 +3365,7 @@ test "std.zon parse float" {
35073365
35083366 // nan as int not allowed
35093367 {
3510 var diag: Diagnostics = .{};
3511 defer diag.deinit(gpa);
3368 var diag: Diagnostics = .init(arena);
35123369 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
35133370 .gpa = gpa,
35143371 .source = "nan",
......@@ -3519,8 +3376,7 @@ test "std.zon parse float" {
35193376
35203377 // nan as int not allowed
35213378 {
3522 var diag: Diagnostics = .{};
3523 defer diag.deinit(gpa);
3379 var diag: Diagnostics = .init(arena);
35243380 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
35253381 .gpa = gpa,
35263382 .source = "nan",
......@@ -3531,8 +3387,7 @@ test "std.zon parse float" {
35313387
35323388 // inf as int not allowed
35333389 {
3534 var diag: Diagnostics = .{};
3535 defer diag.deinit(gpa);
3390 var diag: Diagnostics = .init(arena);
35363391 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
35373392 .gpa = gpa,
35383393 .source = "inf",
......@@ -3543,8 +3398,7 @@ test "std.zon parse float" {
35433398
35443399 // -inf as int not allowed
35453400 {
3546 var diag: Diagnostics = .{};
3547 defer diag.deinit(gpa);
3401 var diag: Diagnostics = .init(arena);
35483402 try std.testing.expectError(error.ParseZon, fromSlice(i8, .{
35493403 .gpa = gpa,
35503404 .source = "-inf",
......@@ -3555,8 +3409,7 @@ test "std.zon parse float" {
35553409
35563410 // Bad identifier as float
35573411 {
3558 var diag: Diagnostics = .{};
3559 defer diag.deinit(gpa);
3412 var diag: Diagnostics = .init(arena);
35603413 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{
35613414 .gpa = gpa,
35623415 .source = "foo",
......@@ -3571,8 +3424,7 @@ test "std.zon parse float" {
35713424 }
35723425
35733426 {
3574 var diag: Diagnostics = .{};
3575 defer diag.deinit(gpa);
3427 var diag: Diagnostics = .init(arena);
35763428 try std.testing.expectError(error.ParseZon, fromSlice(f32, .{
35773429 .gpa = gpa,
35783430 .source = "-foo",
......@@ -3587,17 +3439,25 @@ test "std.zon parse float" {
35873439
35883440 // Non float as float
35893441 {
3590 var diag: Diagnostics = .{};
3591 defer diag.deinit(gpa);
3442 var diag: Diagnostics = .init(arena);
35923443 try std.testing.expectError(
35933444 error.ParseZon,
3594 fromSlice(f32, .{ .gpa = gpa, .source = "\"foo\"", .diag = &diag }),
3445 fromSlice(f32, .{
3446 .gpa = gpa,
3447 .source = "\"foo\"",
3448 .diag = &diag,
3449 }),
35953450 );
35963451 try std.testing.expectFmt("1:1: error: expected type 'f32'\n", "{f}", .{diag});
35973452 }
35983453}
35993454
36003455test "std.zon free on error" {
3456 const gpa = std.testing.allocator;
3457 var arena_allocator: ArenaAllocator = .init(gpa);
3458 defer arena_allocator.deinit();
3459 const arena = arena_allocator.allocator();
3460
36013461 // Test freeing partially allocated structs
36023462 {
36033463 const Struct = struct {
......@@ -3606,7 +3466,8 @@ test "std.zon free on error" {
36063466 z: bool,
36073467 };
36083468 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, .{
3609 .gpa = std.testing.allocator,
3469 .gpa = gpa,
3470 .arena = arena,
36103471 .source =
36113472 \\.{
36123473 \\ .x = "hello",
......@@ -3626,7 +3487,8 @@ test "std.zon free on error" {
36263487 bool,
36273488 };
36283489 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, .{
3629 .gpa = std.testing.allocator,
3490 .gpa = gpa,
3491 .arena = arena,
36303492 .source =
36313493 \\.{
36323494 \\ "hello",
......@@ -3639,58 +3501,55 @@ test "std.zon free on error" {
36393501 }
36403502
36413503 // Test freeing structs with missing fields
3642 {
3643 const Struct = struct {
3644 x: []const u8,
3645 y: bool,
3646 };
3647 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, .{
3648 .gpa = std.testing.allocator,
3649 .source =
3650 \\.{
3651 \\ .x = "hello",
3652 \\}
3653 ,
3654 .diag = null,
3655 }));
3656 }
3504 const Struct = struct {
3505 x: []const u8,
3506 y: bool,
3507 };
3508 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, .{
3509 .gpa = gpa,
3510 .arena = arena,
3511 .source =
3512 \\.{
3513 \\ .x = "hello",
3514 \\}
3515 ,
3516 .diag = null,
3517 }));
36573518
36583519 // Test freeing partially allocated arrays
3659 {
3660 try std.testing.expectError(error.ParseZon, fromSliceAlloc([3][]const u8, .{
3661 .gpa = std.testing.allocator,
3662 .source =
3663 \\.{
3664 \\ "hello",
3665 \\ false,
3666 \\ false,
3667 \\}
3668 ,
3669 .diag = null,
3670 }));
3671 }
3520 try std.testing.expectError(error.ParseZon, fromSliceAlloc([3][]const u8, .{
3521 .gpa = gpa,
3522 .arena = arena,
3523 .source =
3524 \\.{
3525 \\ "hello",
3526 \\ false,
3527 \\ false,
3528 \\}
3529 ,
3530 .diag = null,
3531 }));
36723532
36733533 // Test freeing partially allocated slices
3674 {
3675 try std.testing.expectError(error.ParseZon, fromSliceAlloc([][]const u8, .{
3676 .gpa = std.testing.allocator,
3677 .source =
3678 \\.{
3679 \\ "hello",
3680 \\ "world",
3681 \\ false,
3682 \\}
3683 ,
3684 .diag = null,
3685 }));
3686 }
3534 try std.testing.expectError(error.ParseZon, fromSliceAlloc([][]const u8, .{
3535 .gpa = gpa,
3536 .arena = arena,
3537 .source =
3538 \\.{
3539 \\ "hello",
3540 \\ "world",
3541 \\ false,
3542 \\}
3543 ,
3544 .diag = null,
3545 }));
36873546
36883547 // We can parse types that can't be freed, as long as they contain no allocations, e.g. untagged
36893548 // unions.
36903549 try std.testing.expectEqual(
36913550 @as(f32, 1.5),
36923551 (try fromSlice(union { x: f32 }, .{
3693 .gpa = std.testing.allocator,
3552 .gpa = gpa,
36943553 .source = ".{ .x = 1.5 }",
36953554 .diag = null,
36963555 })).x,
......@@ -3700,80 +3559,13 @@ test "std.zon free on error" {
37003559 // the allocation, as is the case here.
37013560 {
37023561 const result = try fromSliceAlloc(union { x: []const u8 }, .{
3703 .gpa = std.testing.allocator,
3562 .gpa = gpa,
3563 .arena = arena,
37043564 .source = ".{ .x = \"foo\" }",
37053565 .diag = null,
37063566 });
3707 defer free(std.testing.allocator, result.x);
37083567 try std.testing.expectEqualStrings("foo", result.x);
37093568 }
3710
3711 // However, if it's possible we could get an error requiring we free the value, but the value
3712 // cannot be freed (e.g. untagged unions) then we need to turn off `free_on_error` for it to
3713 // compile.
3714 {
3715 const S = struct {
3716 union { x: []const u8 },
3717 bool,
3718 };
3719 const result = try fromSliceAlloc(S, .{
3720 .gpa = std.testing.allocator,
3721 .source = ".{ .{ .x = \"foo\" }, true }",
3722 .free_on_error = false,
3723 .diag = null,
3724 });
3725 defer free(std.testing.allocator, result[0].x);
3726 try std.testing.expectEqualStrings("foo", result[0].x);
3727 try std.testing.expect(result[1]);
3728 }
3729
3730 // Again but for structs.
3731 {
3732 const S = struct {
3733 a: union { x: []const u8 },
3734 b: bool,
3735 };
3736 const result = try fromSliceAlloc(S, .{
3737 .gpa = std.testing.allocator,
3738 .source = ".{ .a = .{ .x = \"foo\" }, .b = true }",
3739 .free_on_error = false,
3740 .diag = null,
3741 });
3742 defer free(std.testing.allocator, result.a.x);
3743 try std.testing.expectEqualStrings("foo", result.a.x);
3744 try std.testing.expect(result.b);
3745 }
3746
3747 // Again but for arrays.
3748 {
3749 const S = [2]union { x: []const u8 };
3750 const result = try fromSliceAlloc(S, .{
3751 .gpa = std.testing.allocator,
3752 .source = ".{ .{ .x = \"foo\" }, .{ .x = \"bar\" } }",
3753 .free_on_error = false,
3754 .diag = null,
3755 });
3756 defer free(std.testing.allocator, result[0].x);
3757 defer free(std.testing.allocator, result[1].x);
3758 try std.testing.expectEqualStrings("foo", result[0].x);
3759 try std.testing.expectEqualStrings("bar", result[1].x);
3760 }
3761
3762 // Again but for slices.
3763 {
3764 const S = []union { x: []const u8 };
3765 const result = try fromSliceAlloc(S, .{
3766 .gpa = std.testing.allocator,
3767 .source = ".{ .{ .x = \"foo\" }, .{ .x = \"bar\" } }",
3768 .free_on_error = false,
3769 .diag = null,
3770 });
3771 defer std.testing.allocator.free(result);
3772 defer free(std.testing.allocator, result[0].x);
3773 defer free(std.testing.allocator, result[1].x);
3774 try std.testing.expectEqualStrings("foo", result[0].x);
3775 try std.testing.expectEqualStrings("bar", result[1].x);
3776 }
37773569}
37783570
37793571test "std.zon vector" {
......@@ -3781,11 +3573,18 @@ test "std.zon vector" {
37813573 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .s390x) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/25957
37823574
37833575 const gpa = std.testing.allocator;
3576 var arena_allocator: ArenaAllocator = .init(gpa);
3577 defer arena_allocator.deinit();
3578 const arena = arena_allocator.allocator();
37843579
37853580 // Passing cases
37863581 try std.testing.expectEqual(
37873582 @Vector(0, bool){},
3788 try fromSlice(@Vector(0, bool), .{ .gpa = gpa, .source = ".{}", .diag = null }),
3583 try fromSlice(@Vector(0, bool), .{
3584 .gpa = gpa,
3585 .source = ".{}",
3586 .diag = null,
3587 }),
37893588 );
37903589 try std.testing.expectEqual(
37913590 @Vector(3, bool){ true, false, true },
......@@ -3798,7 +3597,11 @@ test "std.zon vector" {
37983597
37993598 try std.testing.expectEqual(
38003599 @Vector(0, f32){},
3801 try fromSlice(@Vector(0, f32), .{ .gpa = gpa, .source = ".{}", .diag = null }),
3600 try fromSlice(@Vector(0, f32), .{
3601 .gpa = gpa,
3602 .source = ".{}",
3603 .diag = null,
3604 }),
38023605 );
38033606 try std.testing.expectEqual(
38043607 @Vector(3, f32){ 1.5, 2.5, 3.5 },
......@@ -3811,11 +3614,19 @@ test "std.zon vector" {
38113614
38123615 try std.testing.expectEqual(
38133616 @Vector(0, u8){},
3814 try fromSlice(@Vector(0, u8), .{ .gpa = gpa, .source = ".{}", .diag = null }),
3617 try fromSlice(@Vector(0, u8), .{
3618 .gpa = gpa,
3619 .source = ".{}",
3620 .diag = null,
3621 }),
38153622 );
38163623 try std.testing.expectEqual(
38173624 @Vector(3, u8){ 2, 4, 6 },
3818 try fromSlice(@Vector(3, u8), .{ .gpa = gpa, .source = ".{2, 4, 6}", .diag = null }),
3625 try fromSlice(@Vector(3, u8), .{
3626 .gpa = gpa,
3627 .source = ".{2, 4, 6}",
3628 .diag = null,
3629 }),
38193630 );
38203631
38213632 {
......@@ -3823,16 +3634,17 @@ test "std.zon vector" {
38233634 @Vector(0, *const u8){},
38243635 try fromSliceAlloc(@Vector(0, *const u8), .{
38253636 .gpa = gpa,
3637 .arena = arena,
38263638 .source = ".{}",
38273639 .diag = null,
38283640 }),
38293641 );
38303642 const pointers = try fromSliceAlloc(@Vector(3, *const u8), .{
38313643 .gpa = gpa,
3644 .arena = arena,
38323645 .source = ".{2, 4, 6}",
38333646 .diag = null,
38343647 });
3835 defer free(gpa, pointers);
38363648 try std.testing.expectEqualDeep(@Vector(3, *const u8){ &2, &4, &6 }, pointers);
38373649 }
38383650
......@@ -3841,23 +3653,23 @@ test "std.zon vector" {
38413653 @Vector(0, ?*const u8){},
38423654 try fromSliceAlloc(@Vector(0, ?*const u8), .{
38433655 .gpa = gpa,
3656 .arena = arena,
38443657 .source = ".{}",
38453658 .diag = null,
38463659 }),
38473660 );
38483661 const pointers = try fromSliceAlloc(@Vector(3, ?*const u8), .{
38493662 .gpa = gpa,
3663 .arena = arena,
38503664 .source = ".{2, null, 6}",
38513665 .diag = null,
38523666 });
3853 defer free(gpa, pointers);
38543667 try std.testing.expectEqualDeep(@Vector(3, ?*const u8){ &2, null, &6 }, pointers);
38553668 }
38563669
38573670 // Too few fields
38583671 {
3859 var diag: Diagnostics = .{};
3860 defer diag.deinit(gpa);
3672 var diag: Diagnostics = .init(arena);
38613673 try std.testing.expectError(
38623674 error.ParseZon,
38633675 fromSlice(@Vector(2, f32), .{
......@@ -3875,8 +3687,7 @@ test "std.zon vector" {
38753687
38763688 // Too many fields
38773689 {
3878 var diag: Diagnostics = .{};
3879 defer diag.deinit(gpa);
3690 var diag: Diagnostics = .init(arena);
38803691 try std.testing.expectError(
38813692 error.ParseZon,
38823693 fromSlice(@Vector(2, f32), .{
......@@ -3894,8 +3705,7 @@ test "std.zon vector" {
38943705
38953706 // Wrong type fields
38963707 {
3897 var diag: Diagnostics = .{};
3898 defer diag.deinit(gpa);
3708 var diag: Diagnostics = .init(arena);
38993709 try std.testing.expectError(
39003710 error.ParseZon,
39013711 fromSlice(@Vector(3, f32), .{
......@@ -3913,23 +3723,26 @@ test "std.zon vector" {
39133723
39143724 // Wrong type
39153725 {
3916 var diag: Diagnostics = .{};
3917 defer diag.deinit(gpa);
3726 var diag: Diagnostics = .init(arena);
39183727 try std.testing.expectError(
39193728 error.ParseZon,
3920 fromSlice(@Vector(3, u8), .{ .gpa = gpa, .source = "true", .diag = &diag }),
3729 fromSlice(@Vector(3, u8), .{
3730 .gpa = gpa,
3731 .source = "true",
3732 .diag = &diag,
3733 }),
39213734 );
39223735 try std.testing.expectFmt("1:1: error: expected type '@Vector(3, u8)'\n", "{f}", .{diag});
39233736 }
39243737
39253738 // Elements should get freed on error
39263739 {
3927 var diag: Diagnostics = .{};
3928 defer diag.deinit(gpa);
3740 var diag: Diagnostics = .init(arena);
39293741 try std.testing.expectError(
39303742 error.ParseZon,
39313743 fromSliceAlloc(@Vector(3, *u8), .{
39323744 .gpa = gpa,
3745 .arena = arena,
39333746 .source = ".{1, true, 3}",
39343747 .diag = &diag,
39353748 }),
......@@ -3940,35 +3753,38 @@ test "std.zon vector" {
39403753
39413754test "std.zon add pointers" {
39423755 const gpa = std.testing.allocator;
3756 var arena_allocator: ArenaAllocator = .init(gpa);
3757 defer arena_allocator.deinit();
3758 const arena = arena_allocator.allocator();
39433759
39443760 // Primitive with varying levels of pointers
39453761 {
39463762 const result = try fromSliceAlloc(*u32, .{
39473763 .gpa = gpa,
3764 .arena = arena,
39483765 .source = "10",
39493766 .diag = null,
39503767 });
3951 defer free(gpa, result);
39523768 try std.testing.expectEqual(@as(u32, 10), result.*);
39533769 }
39543770
39553771 {
39563772 const result = try fromSliceAlloc(**u32, .{
39573773 .gpa = gpa,
3774 .arena = arena,
39583775 .source = "10",
39593776 .diag = null,
39603777 });
3961 defer free(gpa, result);
39623778 try std.testing.expectEqual(@as(u32, 10), result.*.*);
39633779 }
39643780
39653781 {
39663782 const result = try fromSliceAlloc(***u32, .{
39673783 .gpa = gpa,
3784 .arena = arena,
39683785 .source = "10",
39693786 .diag = null,
39703787 });
3971 defer free(gpa, result);
39723788 try std.testing.expectEqual(@as(u32, 10), result.*.*.*);
39733789 }
39743790
......@@ -3976,90 +3792,90 @@ test "std.zon add pointers" {
39763792 {
39773793 const some = try fromSliceAlloc(?*u32, .{
39783794 .gpa = gpa,
3795 .arena = arena,
39793796 .source = "10",
39803797 .diag = null,
39813798 });
3982 defer free(gpa, some);
39833799 try std.testing.expectEqual(@as(u32, 10), some.?.*);
39843800
39853801 const none = try fromSliceAlloc(?*u32, .{
39863802 .gpa = gpa,
3803 .arena = arena,
39873804 .source = "null",
39883805 .diag = null,
39893806 });
3990 defer free(gpa, none);
39913807 try std.testing.expectEqual(null, none);
39923808 }
39933809
39943810 {
39953811 const some = try fromSliceAlloc(*?u32, .{
39963812 .gpa = gpa,
3813 .arena = arena,
39973814 .source = "10",
39983815 .diag = null,
39993816 });
4000 defer free(gpa, some);
40013817 try std.testing.expectEqual(@as(u32, 10), some.*.?);
40023818
40033819 const none = try fromSliceAlloc(*?u32, .{
40043820 .gpa = gpa,
3821 .arena = arena,
40053822 .source = "null",
40063823 .diag = null,
40073824 });
4008 defer free(gpa, none);
40093825 try std.testing.expectEqual(null, none.*);
40103826 }
40113827
40123828 {
40133829 const some = try fromSliceAlloc(?**u32, .{
40143830 .gpa = gpa,
3831 .arena = arena,
40153832 .source = "10",
40163833 .diag = null,
40173834 });
4018 defer free(gpa, some);
40193835 try std.testing.expectEqual(@as(u32, 10), some.?.*.*);
40203836
40213837 const none = try fromSliceAlloc(?**u32, .{
40223838 .gpa = gpa,
3839 .arena = arena,
40233840 .source = "null",
40243841 .diag = null,
40253842 });
4026 defer free(gpa, none);
40273843 try std.testing.expectEqual(null, none);
40283844 }
40293845
40303846 {
40313847 const some = try fromSliceAlloc(*?*u32, .{
40323848 .gpa = gpa,
3849 .arena = arena,
40333850 .source = "10",
40343851 .diag = null,
40353852 });
4036 defer free(gpa, some);
40373853 try std.testing.expectEqual(@as(u32, 10), some.*.?.*);
40383854
40393855 const none = try fromSliceAlloc(*?*u32, .{
40403856 .gpa = gpa,
3857 .arena = arena,
40413858 .source = "null",
40423859 .diag = null,
40433860 });
4044 defer free(gpa, none);
40453861 try std.testing.expectEqual(null, none.*);
40463862 }
40473863
40483864 {
40493865 const some = try fromSliceAlloc(**?u32, .{
40503866 .gpa = gpa,
3867 .arena = arena,
40513868 .source = "10",
40523869 .diag = null,
40533870 });
4054 defer free(gpa, some);
40553871 try std.testing.expectEqual(@as(u32, 10), some.*.*.?);
40563872
40573873 const none = try fromSliceAlloc(**?u32, .{
40583874 .gpa = gpa,
3875 .arena = arena,
40593876 .source = "null",
40603877 .diag = null,
40613878 });
4062 defer free(gpa, none);
40633879 try std.testing.expectEqual(null, none.*.*);
40643880 }
40653881
......@@ -4067,10 +3883,10 @@ test "std.zon add pointers" {
40673883 {
40683884 const result = try fromSliceAlloc(*[3]u8, .{
40693885 .gpa = gpa,
3886 .arena = arena,
40703887 .source = ".{ 1, 2, 3 }",
40713888 .diag = null,
40723889 });
4073 defer free(gpa, result);
40743890 try std.testing.expectEqual([3]u8{ 1, 2, 3 }, result.*);
40753891 }
40763892
......@@ -4094,6 +3910,7 @@ test "std.zon add pointers" {
40943910
40953911 const found = try fromSliceAlloc(?*Outer, .{
40963912 .gpa = gpa,
3913 .arena = arena,
40973914 .source =
40983915 \\.{
40993916 \\ .f1 = .{
......@@ -4105,39 +3922,46 @@ test "std.zon add pointers" {
41053922 ,
41063923 .diag = null,
41073924 });
4108 defer free(gpa, found);
41093925
41103926 try std.testing.expectEqualDeep(expected, found.?.*);
41113927 }
41123928
41133929 // Test that optional types are flattened correctly in errors
41143930 {
4115 var diag: Diagnostics = .{};
4116 defer diag.deinit(gpa);
3931 var diag: Diagnostics = .init(arena);
41173932 try std.testing.expectError(
41183933 error.ParseZon,
4119 fromSliceAlloc(*const ?*const u8, .{ .gpa = gpa, .source = "true", .diag = &diag }),
3934 fromSliceAlloc(*const ?*const u8, .{
3935 .gpa = gpa,
3936 .arena = arena,
3937 .source = "true",
3938 .diag = &diag,
3939 }),
41203940 );
41213941 try std.testing.expectFmt("1:1: error: expected type '?u8'\n", "{f}", .{diag});
41223942 }
41233943
41243944 {
4125 var diag: Diagnostics = .{};
4126 defer diag.deinit(gpa);
3945 var diag: Diagnostics = .init(arena);
41273946 try std.testing.expectError(
41283947 error.ParseZon,
4129 fromSliceAlloc(*const ?*const f32, .{ .gpa = gpa, .source = "true", .diag = &diag }),
3948 fromSliceAlloc(*const ?*const f32, .{
3949 .gpa = gpa,
3950 .arena = arena,
3951 .source = "true",
3952 .diag = &diag,
3953 }),
41303954 );
41313955 try std.testing.expectFmt("1:1: error: expected type '?f32'\n", "{f}", .{diag});
41323956 }
41333957
41343958 {
4135 var diag: Diagnostics = .{};
4136 defer diag.deinit(gpa);
3959 var diag: Diagnostics = .init(arena);
41373960 try std.testing.expectError(
41383961 error.ParseZon,
41393962 fromSliceAlloc(*const ?*const @Vector(3, u8), .{
41403963 .gpa = gpa,
3964 .arena = arena,
41413965 .source = "true",
41423966 .diag = &diag,
41433967 }),
......@@ -4146,101 +3970,141 @@ test "std.zon add pointers" {
41463970 }
41473971
41483972 {
4149 var diag: Diagnostics = .{};
4150 defer diag.deinit(gpa);
3973 var diag: Diagnostics = .init(arena);
41513974 try std.testing.expectError(
41523975 error.ParseZon,
4153 fromSliceAlloc(*const ?*const bool, .{ .gpa = gpa, .source = "10", .diag = &diag }),
3976 fromSliceAlloc(*const ?*const bool, .{
3977 .gpa = gpa,
3978 .arena = arena,
3979 .source = "10",
3980 .diag = &diag,
3981 }),
41543982 );
41553983 try std.testing.expectFmt("1:1: error: expected type '?bool'\n", "{f}", .{diag});
41563984 }
41573985
41583986 {
4159 var diag: Diagnostics = .{};
4160 defer diag.deinit(gpa);
3987 var diag: Diagnostics = .init(arena);
41613988 try std.testing.expectError(
41623989 error.ParseZon,
4163 fromSliceAlloc(*const ?*const struct { a: i32 }, .{ .gpa = gpa, .source = "true", .diag = &diag }),
3990 fromSliceAlloc(*const ?*const struct { a: i32 }, .{
3991 .gpa = gpa,
3992 .arena = arena,
3993 .source = "true",
3994 .diag = &diag,
3995 }),
41643996 );
41653997 try std.testing.expectFmt("1:1: error: expected optional struct\n", "{f}", .{diag});
41663998 }
41673999
41684000 {
4169 var diag: Diagnostics = .{};
4170 defer diag.deinit(gpa);
4001 var diag: Diagnostics = .init(arena);
41714002 try std.testing.expectError(
41724003 error.ParseZon,
4173 fromSliceAlloc(*const ?*const struct { i32 }, .{ .gpa = gpa, .source = "true", .diag = &diag }),
4004 fromSliceAlloc(*const ?*const struct { i32 }, .{
4005 .gpa = gpa,
4006 .arena = arena,
4007 .source = "true",
4008 .diag = &diag,
4009 }),
41744010 );
41754011 try std.testing.expectFmt("1:1: error: expected optional tuple\n", "{f}", .{diag});
41764012 }
41774013
41784014 {
4179 var diag: Diagnostics = .{};
4180 defer diag.deinit(gpa);
4015 var diag: Diagnostics = .init(arena);
41814016 try std.testing.expectError(
41824017 error.ParseZon,
4183 fromSliceAlloc(*const ?*const union { x: void }, .{ .gpa = gpa, .source = "true", .diag = &diag }),
4018 fromSliceAlloc(*const ?*const union { x: void }, .{
4019 .gpa = gpa,
4020 .arena = arena,
4021 .source = "true",
4022 .diag = &diag,
4023 }),
41844024 );
41854025 try std.testing.expectFmt("1:1: error: expected optional union\n", "{f}", .{diag});
41864026 }
41874027
41884028 {
4189 var diag: Diagnostics = .{};
4190 defer diag.deinit(gpa);
4029 var diag: Diagnostics = .init(arena);
41914030 try std.testing.expectError(
41924031 error.ParseZon,
4193 fromSliceAlloc(*const ?*const [3]u8, .{ .gpa = gpa, .source = "true", .diag = &diag }),
4032 fromSliceAlloc(*const ?*const [3]u8, .{
4033 .gpa = gpa,
4034 .arena = arena,
4035 .source = "true",
4036 .diag = &diag,
4037 }),
41944038 );
41954039 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
41964040 }
41974041
41984042 {
4199 var diag: Diagnostics = .{};
4200 defer diag.deinit(gpa);
4043 var diag: Diagnostics = .init(arena);
42014044 try std.testing.expectError(
42024045 error.ParseZon,
4203 fromSliceAlloc(?[3]u8, .{ .gpa = gpa, .source = "true", .diag = &diag }),
4046 fromSliceAlloc(?[3]u8, .{
4047 .gpa = gpa,
4048 .arena = arena,
4049 .source = "true",
4050 .diag = &diag,
4051 }),
42044052 );
42054053 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
42064054 }
42074055
42084056 {
4209 var diag: Diagnostics = .{};
4210 defer diag.deinit(gpa);
4057 var diag: Diagnostics = .init(arena);
42114058 try std.testing.expectError(
42124059 error.ParseZon,
4213 fromSliceAlloc(*const ?*const []u8, .{ .gpa = gpa, .source = "true", .diag = &diag }),
4060 fromSliceAlloc(*const ?*const []u8, .{
4061 .gpa = gpa,
4062 .arena = arena,
4063 .source = "true",
4064 .diag = &diag,
4065 }),
42144066 );
42154067 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
42164068 }
42174069
42184070 {
4219 var diag: Diagnostics = .{};
4220 defer diag.deinit(gpa);
4071 var diag: Diagnostics = .init(arena);
42214072 try std.testing.expectError(
42224073 error.ParseZon,
4223 fromSliceAlloc(?[]u8, .{ .gpa = gpa, .source = "true", .diag = &diag }),
4074 fromSliceAlloc(?[]u8, .{
4075 .gpa = gpa,
4076 .arena = arena,
4077 .source = "true",
4078 .diag = &diag,
4079 }),
42244080 );
42254081 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
42264082 }
42274083
42284084 {
4229 var diag: Diagnostics = .{};
4230 defer diag.deinit(gpa);
4085 var diag: Diagnostics = .init(arena);
42314086 try std.testing.expectError(
42324087 error.ParseZon,
4233 fromSliceAlloc(*const ?*const []const u8, .{ .gpa = gpa, .source = "true", .diag = &diag }),
4088 fromSliceAlloc(*const ?*const []const u8, .{
4089 .gpa = gpa,
4090 .arena = arena,
4091 .source = "true",
4092 .diag = &diag,
4093 }),
42344094 );
42354095 try std.testing.expectFmt("1:1: error: expected optional string\n", "{f}", .{diag});
42364096 }
42374097
42384098 {
4239 var diag: Diagnostics = .{};
4240 defer diag.deinit(gpa);
4099 var diag: Diagnostics = .init(arena);
42414100 try std.testing.expectError(
42424101 error.ParseZon,
4243 fromSliceAlloc(*const ?*const enum { foo }, .{ .gpa = gpa, .source = "true", .diag = &diag }),
4102 fromSliceAlloc(*const ?*const enum { foo }, .{
4103 .gpa = gpa,
4104 .arena = arena,
4105 .source = "true",
4106 .diag = &diag,
4107 }),
42444108 );
42454109 try std.testing.expectFmt("1:1: error: expected optional enum literal\n", "{f}", .{diag});
42464110 }
......@@ -4255,26 +4119,35 @@ test "std.zon stop on node" {
42554119 y: f32,
42564120 };
42574121
4258 var diag: Diagnostics = .{};
4259 defer diag.deinit(gpa);
4260 const result = try fromSlice(Vec2, .{
4261 .gpa = gpa,
4262 .source = ".{ .x = 1.5, .y = 2.5 }",
4263 .diag = &diag,
4122 var ast = try std.zig.Ast.parse(gpa, ".{ .x = 1.5, .y = 2.5 }", .{ .mode = .zon });
4123 defer ast.deinit(gpa);
4124
4125 var zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false });
4126 defer zoir.deinit(gpa);
4127
4128 const result = try fromZoir(Vec2, .{
4129 .ast = &ast,
4130 .zoir = &zoir,
4131 .diag = null,
42644132 });
4133
42654134 try std.testing.expectEqual(result.y, 2.5);
4266 try std.testing.expectEqual(Zoir.Node{ .float_literal = 1.5 }, result.x.get(diag.zoir));
4135 try std.testing.expectEqual(Zoir.Node{ .float_literal = 1.5 }, result.x.get(&zoir));
42674136 }
42684137
42694138 {
4270 var diag: Diagnostics = .{};
4271 defer diag.deinit(gpa);
4272 const result = try fromSlice(Zoir.Node.Index, .{
4273 .gpa = gpa,
4274 .source = "1.23",
4275 .diag = &diag,
4139 var ast = try std.zig.Ast.parse(gpa, "1.23", .{ .mode = .zon });
4140 defer ast.deinit(gpa);
4141
4142 var zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false });
4143 defer zoir.deinit(gpa);
4144
4145 const result = try fromZoir(Zoir.Node.Index, .{
4146 .ast = &ast,
4147 .zoir = &zoir,
4148 .diag = null,
42764149 });
4277 try std.testing.expectEqual(Zoir.Node{ .float_literal = 1.23 }, result.get(diag.zoir));
4150 try std.testing.expectEqual(Zoir.Node{ .float_literal = 1.23 }, result.get(&zoir));
42784151 }
42794152}
42804153
......@@ -4300,12 +4173,19 @@ test "std.zon no alloc" {
43004173
43014174 try std.testing.expectEqual(
43024175 Nested{ 1, 2, .{ 3, 4 } },
4303 try fromZoir(Nested, .{ .ast = ast, .zoir = zoir, .diag = null }),
4176 try fromZoir(Nested, .{
4177 .ast = &ast,
4178 .zoir = &zoir,
4179 .diag = null,
4180 }),
43044181 );
43054182}
43064183
43074184test "std.zon errors without diagnostics" {
43084185 const gpa = std.testing.allocator;
4186 var arena_allocator: ArenaAllocator = .init(gpa);
4187 defer arena_allocator.deinit();
4188 const arena = arena_allocator.allocator();
43094189
43104190 const Enum = enum {
43114191 foo,
......@@ -4314,6 +4194,7 @@ test "std.zon errors without diagnostics" {
43144194 };
43154195 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Enum, .{
43164196 .gpa = gpa,
4197 .arena = arena,
43174198 .source = ".nothing",
43184199 .diag = null,
43194200 }));
......@@ -4323,6 +4204,7 @@ test "std.zon errors without diagnostics" {
43234204 };
43244205 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, .{
43254206 .gpa = gpa,
4207 .arena = arena,
43264208 .source = ".{ .name = \"Alice\", .age = 25 }",
43274209 .diag = null,
43284210 }));
......@@ -4333,11 +4215,13 @@ test "std.zon errors without diagnostics" {
43334215 };
43344216 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{
43354217 .gpa = gpa,
4218 .arena = arena,
43364219 .source = ".a",
43374220 .diag = null,
43384221 }));
43394222 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, .{
43404223 .gpa = gpa,
4224 .arena = arena,
43414225 .source = ".{ .b = 8 }",
43424226 .diag = null,
43434227 }));
......@@ -4345,6 +4229,9 @@ test "std.zon errors without diagnostics" {
43454229
43464230test "std.zon aligned pointers" {
43474231 const gpa = std.testing.allocator;
4232 var arena_allocator: ArenaAllocator = .init(gpa);
4233 defer arena_allocator.deinit();
4234 const arena = arena_allocator.allocator();
43484235
43494236 const n: u8 align(8) = 10;
43504237 const Foo = struct {
......@@ -4356,15 +4243,18 @@ test "std.zon aligned pointers" {
43564243 };
43574244 const found = try fromSliceAlloc(Foo, .{
43584245 .gpa = gpa,
4246 .arena = arena,
43594247 .source = ".{ .inner = 10 }",
43604248 .diag = null,
43614249 });
4362 defer free(gpa, found);
43634250 try std.testing.expectEqualDeep(expected.inner, found.inner);
43644251}
43654252
43664253test "std.zon update" {
43674254 const gpa = std.testing.allocator;
4255 var arena_allocator: ArenaAllocator = .init(gpa);
4256 defer arena_allocator.deinit();
4257 const arena = arena_allocator.allocator();
43684258
43694259 const Vector = struct { x: f32, y: f32, z: f32 };
43704260 const MyStruct = struct {
......@@ -4379,51 +4269,43 @@ test "std.zon update" {
43794269 str: []const u8,
43804270 };
43814271
4272 var v1: Vector = .{ .x = 1, .y = 2, .z = 3 };
43824273 var expected: MyStruct = .{
43834274 .foo = 10,
43844275 .bar = true,
43854276 .baz = .{ .a = .{ 1, 2 }, .b = .c },
4386 .ptr = b: {
4387 const v = gpa.create(Vector) catch @panic("oom");
4388 v.* = .{ .x = 1, .y = 2, .z = 3 };
4389 break :b v;
4390 },
4391 .str = gpa.dupe(u8, "hello, world") catch @panic("oom"),
4277 .ptr = &v1,
4278 .str = "hello, world",
43924279 };
4393 defer free(gpa, expected);
4280 var v2: Vector = .{ .x = 1, .y = 2, .z = 3 };
43944281 var found: MyStruct = .{
43954282 .foo = 10,
43964283 .bar = true,
43974284 .baz = .{ .a = .{ 1, 2 }, .b = .c },
4398 .ptr = b: {
4399 const v = gpa.create(Vector) catch @panic("oom");
4400 v.* = .{ .x = 1, .y = 2, .z = 3 };
4401 break :b v;
4402 },
4403 .str = gpa.dupe(u8, "hello, world") catch @panic("oom"),
4285 .ptr = &v2,
4286 .str = "hello, world",
44044287 };
4405 defer free(gpa, found);
44064288
4407 try updateFromSliceAlloc(MyStruct, .{
4289 try updateFromSliceAlloc(MyStruct, &found, .{
44084290 .gpa = gpa,
4409 .value = &found,
4291 .arena = arena,
44104292 .source = ".{}",
44114293 .diag = null,
44124294 });
44134295 try std.testing.expectEqualDeep(expected, found);
44144296
4415 try updateFromSliceAlloc(MyStruct, .{
4297 try updateFromSliceAlloc(MyStruct, &found, .{
44164298 .gpa = gpa,
4417 .value = &found,
4299 .arena = arena,
44184300 .source = ".{ .bar = false }",
44194301 .diag = null,
44204302 });
44214303 expected.bar = false;
44224304 try std.testing.expectEqualDeep(expected, found);
44234305
4424 try updateFromSliceAlloc(MyStruct, .{
4306 try updateFromSliceAlloc(MyStruct, &found, .{
44254307 .gpa = gpa,
4426 .value = &found,
4308 .arena = arena,
44274309 .source = ".{ .baz = .{ .a = .{ 2, 4 } } }",
44284310 .diag = null,
44294311 });
......@@ -4431,9 +4313,9 @@ test "std.zon update" {
44314313 expected.baz.a[1] = 4;
44324314 try std.testing.expectEqualDeep(expected, found);
44334315
4434 try updateFromSliceAlloc(MyStruct, .{
4316 try updateFromSliceAlloc(MyStruct, &found, .{
44354317 .gpa = gpa,
4436 .value = &found,
4318 .arena = arena,
44374319 .source = ".{ .foo = 11, .baz = .{ .b = .d } }",
44384320 .diag = null,
44394321 });
......@@ -4441,27 +4323,27 @@ test "std.zon update" {
44414323 expected.baz.b = .d;
44424324 try std.testing.expectEqualDeep(expected, found);
44434325
4444 try updateFromSliceAlloc(MyStruct, .{
4326 try updateFromSliceAlloc(MyStruct, &found, .{
44454327 .gpa = gpa,
4446 .value = &found,
4328 .arena = arena,
44474329 .source = ".{ .optional = 10 }",
44484330 .diag = null,
44494331 });
44504332 expected.optional = 10;
44514333 try std.testing.expectEqualDeep(expected, found);
44524334
4453 try updateFromSliceAlloc(MyStruct, .{
4335 try updateFromSliceAlloc(MyStruct, &found, .{
44544336 .gpa = gpa,
4455 .value = &found,
4337 .arena = arena,
44564338 .source = ".{ .optional = null }",
44574339 .diag = null,
44584340 });
44594341 expected.optional = null;
44604342 try std.testing.expectEqualDeep(expected, found);
44614343
4462 try updateFromSliceAlloc(MyStruct, .{
4344 try updateFromSliceAlloc(MyStruct, &found, .{
44634345 .gpa = gpa,
4464 .value = &found,
4346 .arena = arena,
44654347 .source = ".{ .ptr = .{ .x = 10, .y = 20, .z = 30 } }",
44664348 .diag = null,
44674349 });
......@@ -4470,14 +4352,13 @@ test "std.zon update" {
44704352 expected.ptr.z = 30;
44714353 try std.testing.expectEqualDeep(expected, found);
44724354
4473 try updateFromSliceAlloc(MyStruct, .{
4355 try updateFromSliceAlloc(MyStruct, &found, .{
44744356 .gpa = gpa,
4475 .value = &found,
4357 .arena = arena,
44764358 .source = ".{ .str = \"foo\" }",
44774359 .diag = null,
44784360 });
4479 gpa.free(expected.str);
4480 expected.str = gpa.dupe(u8, "foo") catch @panic("oom");
4361 expected.str = "foo";
44814362 try std.testing.expectEqualDeep(expected, found);
44824363}
44834364
......@@ -4486,6 +4367,9 @@ test "std.zon variants" {
44864367 // the same code.
44874368
44884369 const gpa = std.testing.allocator;
4370 var arena_allocator: ArenaAllocator = .init(gpa);
4371 defer arena_allocator.deinit();
4372 const arena = arena_allocator.allocator();
44894373
44904374 const Struct = struct { a: u32, b: u32 };
44914375 const start: Struct = .{ .a = 10, .b = 20 };
......@@ -4499,38 +4383,35 @@ test "std.zon variants" {
44994383 defer zoir.deinit(gpa);
45004384
45014385 var curr = start;
4502 try updateFromSlice(Struct, .{
4386 try updateFromSlice(Struct, &curr, .{
45034387 .gpa = gpa,
4504 .value = &curr,
45054388 .source = ".{ .a = 100 }",
45064389 .diag = null,
45074390 });
45084391 try std.testing.expectEqual(end, curr);
45094392
45104393 curr = start;
4511 try updateFromSliceAlloc(Struct, .{
4394 try updateFromSliceAlloc(Struct, &curr, .{
45124395 .gpa = gpa,
4513 .value = &curr,
4396 .arena = arena,
45144397 .source = ".{ .a = 100 }",
45154398 .diag = null,
45164399 });
45174400 try std.testing.expectEqual(end, curr);
45184401
45194402 curr = start;
4520 try updateFromZoir(Struct, .{
4521 .ast = ast,
4522 .value = &curr,
4523 .zoir = zoir,
4403 try updateFromZoir(Struct, &curr, .{
4404 .ast = &ast,
4405 .zoir = &zoir,
45244406 .diag = null,
45254407 });
45264408 try std.testing.expectEqual(end, curr);
45274409
45284410 curr = start;
4529 try updateFromZoirAlloc(Struct, .{
4530 .gpa = gpa,
4531 .value = &curr,
4532 .ast = ast,
4533 .zoir = zoir,
4411 try updateFromZoirAlloc(Struct, &curr, .{
4412 .arena = arena,
4413 .ast = &ast,
4414 .zoir = &zoir,
45344415 .diag = null,
45354416 });
45364417 try std.testing.expectEqual(end, curr);
......@@ -4555,23 +4436,24 @@ test "std.zon variants" {
45554436 end,
45564437 try fromSliceAlloc(Struct, .{
45574438 .gpa = gpa,
4439 .arena = arena,
45584440 .source = ".{ .a = 100, .b = 20 }",
45594441 .diag = null,
45604442 }),
45614443 );
45624444 try std.testing.expectEqual(
45634445 try fromZoir(Struct, .{
4564 .ast = ast,
4565 .zoir = zoir,
4446 .ast = &ast,
4447 .zoir = &zoir,
45664448 .diag = null,
45674449 }),
45684450 end,
45694451 );
45704452 try std.testing.expectEqual(
45714453 try fromZoirAlloc(Struct, .{
4572 .gpa = gpa,
4573 .ast = ast,
4574 .zoir = zoir,
4454 .arena = arena,
4455 .ast = &ast,
4456 .zoir = &zoir,
45754457 .diag = null,
45764458 }),
45774459 end,