authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2026-07-08 10:54:42+02:00
committergravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2026-07-08 15:49:18+02:00
log3e45baa60adbb041bf75af4cde380abb3b05abfb
tree37e8dd5a927db98f16ad8b9eadd1b4c41aa27959
parent9953d7edca95ddd6ee0a517f33fa8f390cfe04c8
signaturelock-open Commit is signed but in an unrecognized format.

std.zig.Ast.parse: introduce options struct

This is a much cleaner way to expose the new option to disable recovery added in 62720ad9f9e65dd8c625. It also makes it possible to add further options in the future without further breaking changes.

16 files changed, 37 insertions(+), 37 deletions(-)

lib/compiler/Maker.zig+1-1
......@@ -3536,7 +3536,7 @@ fn loadManifest(
35363536 else => |e| fatal("unable to load {s}: {t}", .{ Package.Manifest.basename, e }),
35373537 };
35383538 };
3539 var ast = try std.zig.Ast.parse(gpa, manifest_bytes, .zon);
3539 var ast = try std.zig.Ast.parse(gpa, manifest_bytes, .zon, .{});
35403540 errdefer ast.deinit(gpa);
35413541
35423542 if (ast.errors.len > 0) {
lib/compiler/Maker/Package/Manifest.zig+4-4
......@@ -597,7 +597,7 @@ pub fn load(
597597 0,
598598 );
599599
600 ast.* = try std.zig.Ast.parse(arena, manifest_bytes, .zon);
600 ast.* = try std.zig.Ast.parse(arena, manifest_bytes, .zon, .{});
601601
602602 if (ast.errors.len > 0) {
603603 const file_path = try manifest_path.joinString(arena, "");
......@@ -636,7 +636,7 @@ test "basic" {
636636 \\}
637637 ;
638638
639 var ast = try Ast.parse(gpa, example, .zon);
639 var ast = try Ast.parse(gpa, example, .zon, .{});
640640 defer ast.deinit(gpa);
641641
642642 try testing.expect(ast.errors.len == 0);
......@@ -682,7 +682,7 @@ test "minimum_zig_version" {
682682 \\}
683683 ;
684684
685 var ast = try Ast.parse(gpa, example, .zon);
685 var ast = try Ast.parse(gpa, example, .zon, .{});
686686 defer ast.deinit(gpa);
687687
688688 try testing.expect(ast.errors.len == 0);
......@@ -717,7 +717,7 @@ test "minimum_zig_version - invalid version" {
717717 \\}
718718 ;
719719
720 var ast = try Ast.parse(gpa, example, .zon);
720 var ast = try Ast.parse(gpa, example, .zon, .{});
721721 defer ast.deinit(gpa);
722722
723723 try testing.expect(ast.errors.len == 0);
lib/compiler/reduce.zig+2-2
......@@ -188,7 +188,7 @@ pub fn main(init: std.process.Init) !void {
188188 try astgen_input.writer.writeAll(rendered.written());
189189 try astgen_input.writer.writeByte(0);
190190 const source_with_null = astgen_input.written()[0..(astgen_input.written().len - 1) :0];
191 var astgen_tree = try Ast.parse(gpa, source_with_null, .zig);
191 var astgen_tree = try Ast.parse(gpa, source_with_null, .zig, .{});
192192 defer astgen_tree.deinit(gpa);
193193 if (astgen_tree.errors.len != 0) {
194194 @panic("syntax errors occurred");
......@@ -407,7 +407,7 @@ fn parse(gpa: Allocator, io: Io, file_path: []const u8) !Ast {
407407 };
408408 errdefer gpa.free(source_code);
409409
410 var tree = try Ast.parse(gpa, source_code, .zig);
410 var tree = try Ast.parse(gpa, source_code, .zig, .{});
411411 errdefer tree.deinit(gpa);
412412
413413 if (tree.errors.len != 0) {
lib/docs/wasm/Walk.zig+3-3
......@@ -428,7 +428,7 @@ fn parse(file_name: []const u8, source: []u8) Oom!Ast {
428428 break :s source[0 .. source.len - 1 :0];
429429 };
430430
431 var ast = try Ast.parse(gpa, adjusted_source, .zig);
431 var ast = try Ast.parse(gpa, adjusted_source, .zig, .{});
432432 if (ast.errors.len > 0) {
433433 defer ast.deinit(gpa);
434434
......@@ -446,7 +446,7 @@ fn parse(file_name: []const u8, source: []u8) Oom!Ast {
446446 file_name, err_loc.line + 1, err_loc.column + 1, rendered_err.written(),
447447 });
448448 }
449 return Ast.parse(gpa, "", .zig);
449 return Ast.parse(gpa, "", .zig, .{});
450450 }
451451 return ast;
452452}
......@@ -1085,7 +1085,7 @@ pub fn isPrimitiveNonType(name: []const u8) bool {
10851085//
10861086// // example test command:
10871087// // zig test --dep input.zig -Mroot=src/Walk.zig -Minput.zig=/home/andy/dev/zig/lib/std/fs/File/zig
1088// var ast = try Ast.parse(gpa, @embedFile("input.zig"), .zig);
1088// var ast = try Ast.parse(gpa, @embedFile("input.zig"), .zig, .{});
10891089// defer ast.deinit(gpa);
10901090//
10911091// var w: Walk = .{
lib/std/zig/Ast.zig+8-8
......@@ -138,11 +138,14 @@ pub fn deinit(tree: *Ast, gpa: Allocator) void {
138138 tree.* = undefined;
139139}
140140
141pub const Mode = enum { zig, zon, zig_no_recover };
141pub const Mode = enum { zig, zon };
142pub const ParseOptions = struct {
143 recover: bool = true,
144};
142145
143146/// Result should be freed with tree.deinit() when there are
144147/// no more references to any of the tokens or nodes.
145pub fn parse(gpa: Allocator, source: [:0]const u8, mode: Mode) Allocator.Error!Ast {
148pub fn parse(gpa: Allocator, source: [:0]const u8, mode: Mode, options: ParseOptions) Allocator.Error!Ast {
146149 var tokens = Ast.TokenList{};
147150 defer tokens.deinit(gpa);
148151
......@@ -162,7 +165,7 @@ pub fn parse(gpa: Allocator, source: [:0]const u8, mode: Mode) Allocator.Error!A
162165
163166 var tokens_slice = tokens.toOwnedSlice();
164167 errdefer tokens_slice.deinit(gpa);
165 return parseTokens(gpa, source, tokens_slice, mode);
168 return parseTokens(gpa, source, tokens_slice, mode, options);
166169}
167170
168171pub fn parseTokens(
......@@ -170,6 +173,7 @@ pub fn parseTokens(
170173 source: [:0]const u8,
171174 tokens: Ast.TokenList.Slice,
172175 mode: Mode,
176 options: ParseOptions,
173177) Allocator.Error!Ast {
174178 var parser: Parse = .{
175179 .source = source,
......@@ -180,7 +184,7 @@ pub fn parseTokens(
180184 .extra_data = .empty,
181185 .scratch = .empty,
182186 .tok_i = 0,
183 .recover = true,
187 .recover = options.recover,
184188 };
185189 defer parser.errors.deinit(gpa);
186190 defer parser.nodes.deinit(gpa);
......@@ -194,10 +198,6 @@ pub fn parseTokens(
194198
195199 switch (mode) {
196200 .zig => try parser.parseRoot(),
197 .zig_no_recover => {
198 parser.recover = false;
199 try parser.parseRoot();
200 },
201201 .zon => try parser.parseZon(),
202202 }
203203
lib/std/zig/parser_fuzz.zig+1-1
......@@ -171,7 +171,7 @@ fn checkAgainstOracle(source: [:0]const u8) !void {
171171 // error right away and does no recovery. However, std.zig.Ast.parse() does recovery
172172 // by default and will hit a stack overflow rather than returning after the parser error.
173173 // Stack overflows are not interesting and we do not want the fuzzer to be able to find them.
174 const ast = try std.zig.Ast.parse(fba.allocator(), source, .zig_no_recover);
174 const ast = try std.zig.Ast.parse(fba.allocator(), source, .zig, .{ .recover = false });
175175
176176 errdefer logBadSource(source, ast);
177177 try std.testing.expectEqual(expected, ast.errors.len == 0);
lib/std/zig/parser_test.zig+4-4
......@@ -7231,7 +7231,7 @@ test "ampersand" {
72317231test "Ast: pointer types with subexprs containing qualifiers" {
72327232 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
72337233 const allocator = fixed_allocator.allocator();
7234 var tree = try std.zig.Ast.parse(allocator, "**addrspace(*align(1)T)T", .zon);
7234 var tree = try std.zig.Ast.parse(allocator, "**addrspace(*align(1)T)T", .zon, .{});
72357235 defer tree.deinit(allocator);
72367236
72377237 const regular_ptr_node = tree.nodeData(.root).node;
......@@ -7253,7 +7253,7 @@ fn testParse(io: Io, source: [:0]const u8, allocator: Allocator, anything_change
72537253 defer io.unlockStderr();
72547254 const writer = &stderr.file_writer.interface;
72557255
7256 var tree = try std.zig.Ast.parse(allocator, source, .zig);
7256 var tree = try std.zig.Ast.parse(allocator, source, .zig, .{});
72577257 defer tree.deinit(allocator);
72587258
72597259 for (tree.errors) |parse_error| {
......@@ -7313,7 +7313,7 @@ fn testCanonical(source: [:0]const u8) !void {
73137313const Error = std.zig.Ast.Error.Tag;
73147314
73157315fn testError(source: [:0]const u8, expected_errors: []const Error) !void {
7316 var tree = try std.zig.Ast.parse(std.testing.allocator, source, .zig);
7316 var tree = try std.zig.Ast.parse(std.testing.allocator, source, .zig, .{});
73177317 defer tree.deinit(std.testing.allocator);
73187318
73197319 std.testing.expectEqual(expected_errors.len, tree.errors.len) catch |err| {
......@@ -7333,5 +7333,5 @@ fn fuzzTestOneParse(_: void, smith: *std.testing.Smith) !void {
73337333 const mode = smith.value(std.zig.Ast.Mode);
73347334 var tokens: std.zig.TokenSmith = .gen(smith);
73357335 var fba: std.heap.FixedBufferAllocator = .init(&fixed_buffer_mem);
7336 _ = std.zig.Ast.parseTokens(fba.allocator(), tokens.source(), tokens.list(), mode) catch return;
7336 _ = std.zig.Ast.parseTokens(fba.allocator(), tokens.source(), tokens.list(), mode, .{ .recover = false }) catch return;
73377337}
lib/std/zig/perf_test.zig+1-1
......@@ -32,6 +32,6 @@ pub fn main() !void {
3232fn testOnce() usize {
3333 var fixed_buf_alloc = std.heap.FixedBufferAllocator.init(&fixed_buffer_mem);
3434 const allocator = fixed_buf_alloc.allocator();
35 _ = std.zig.Ast.parse(allocator, source, .zig) catch @panic("parse failure");
35 _ = std.zig.Ast.parse(allocator, source, .zig, .{}) catch @panic("parse failure");
3636 return fixed_buf_alloc.end_index;
3737}
lib/std/zon/parse.zig+3-3
......@@ -294,7 +294,7 @@ pub fn fromSliceAlloc(
294294) error{ OutOfMemory, ParseZon }!T {
295295 if (diag) |s| s.assertEmpty();
296296
297 var ast = try std.zig.Ast.parse(gpa, source, .zon);
297 var ast = try std.zig.Ast.parse(gpa, source, .zon, .{});
298298 defer if (diag == null) ast.deinit(gpa);
299299 if (diag) |s| s.ast = ast;
300300
......@@ -2140,7 +2140,7 @@ test "std.zon string literal" {
21402140 // Passing string literal to a array
21412141 {
21422142 {
2143 var ast = try std.zig.Ast.parse(gpa, "\"abcd\"", .zon);
2143 var ast = try std.zig.Ast.parse(gpa, "\"abcd\"", .zon, .{});
21442144 defer ast.deinit(gpa);
21452145 var zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false });
21462146 defer zoir.deinit(gpa);
......@@ -3534,7 +3534,7 @@ test "std.zon no alloc" {
35343534
35353535 const Nested = struct { u8, u8, struct { u8, u8 } };
35363536
3537 var ast = try std.zig.Ast.parse(gpa, ".{ 1, 2, .{ 3, 4 } }", .zon);
3537 var ast = try std.zig.Ast.parse(gpa, ".{ 1, 2, .{ 3, 4 } }", .zon, .{});
35383538 defer ast.deinit(gpa);
35393539
35403540 var zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false });
src/Builtin.zig+1-1
......@@ -296,7 +296,7 @@ pub fn populateFile(opts: @This(), gpa: Allocator, file: *File) Allocator.Error!
296296
297297 log.debug("parsing and generating 'builtin.zig'", .{});
298298
299 file.tree = try std.zig.Ast.parse(gpa, file.source.?, .zig);
299 file.tree = try std.zig.Ast.parse(gpa, file.source.?, .zig, .{});
300300 assert(file.tree.?.errors.len == 0); // builtin.zig must parse
301301
302302 file.zir = try AstGen.generate(gpa, file.tree.?);
src/Zcu.zig+1-1
......@@ -1145,7 +1145,7 @@ pub const File = struct {
11451145 if (file.tree) |*tree| return tree;
11461146
11471147 const source = try file.getSource(zcu);
1148 file.tree = try .parse(zcu.gpa, source, file.getMode());
1148 file.tree = try .parse(zcu.gpa, source, file.getMode(), .{});
11491149 return &file.tree.?;
11501150 }
11511151
src/Zcu/PerThread.zig+1-1
......@@ -642,7 +642,7 @@ pub fn updateFile(
642642
643643 var timer = comp.startTimer();
644644 // Any potential AST errors are converted to ZIR errors when we run AstGen/ZonGen.
645 file.tree = try Ast.parse(gpa, source, file.getMode());
645 file.tree = try Ast.parse(gpa, source, file.getMode(), .{});
646646 if (timer.finish(io)) |ns_parse| {
647647 comp.mutex.lockUncancelable(io);
648648 defer comp.mutex.unlock(io);
src/fmt.zig+2-2
......@@ -117,7 +117,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !
117117 };
118118 defer gpa.free(source_code);
119119
120 var tree = std.zig.Ast.parse(gpa, source_code, if (force_zon) .zon else .zig) catch |err| {
120 var tree = std.zig.Ast.parse(gpa, source_code, if (force_zon) .zon else .zig, .{}) catch |err| {
121121 fatal("error parsing stdin: {}", .{err});
122122 };
123123 defer tree.deinit(gpa);
......@@ -312,7 +312,7 @@ fn fmtPathFile(
312312 break :mode .zig;
313313 };
314314
315 var tree = try std.zig.Ast.parse(gpa, source_code, mode);
315 var tree = try std.zig.Ast.parse(gpa, source_code, mode, .{});
316316 defer tree.deinit(gpa);
317317
318318 if (tree.errors.len != 0) {
src/main.zig+3-3
......@@ -5529,7 +5529,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8, environ_map:
55295529 break :mode .zig;
55305530 };
55315531
5532 const tree = try Ast.parse(arena, source, mode);
5532 const tree = try Ast.parse(arena, source, mode, .{});
55335533
55345534 var stdout_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer);
55355535 const stdout_bw = &stdout_writer.interface;
......@@ -5699,7 +5699,7 @@ fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8, environ_map
56995699 fatal("unable to read new source file {q}: {t}", .{ new_source_path, err });
57005700 };
57015701
5702 const old_tree = try Ast.parse(arena, old_source, .zig);
5702 const old_tree = try Ast.parse(arena, old_source, .zig, .{});
57035703 const old_zir = try AstGen.generate(arena, old_tree);
57045704
57055705 if (old_zir.loweringFailed()) {
......@@ -5711,7 +5711,7 @@ fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8, environ_map
57115711 process.exit(1);
57125712 }
57135713
5714 const new_tree = try Ast.parse(arena, new_source, .zig);
5714 const new_tree = try Ast.parse(arena, new_source, .zig, .{});
57155715 const new_zir = try AstGen.generate(arena, new_tree);
57165716
57175717 if (new_zir.loweringFailed()) {
tools/gen_parser_oracle.zig+1-1
......@@ -43,7 +43,7 @@ pub fn main(init: std.process.Init) !void {
4343 defer gpa.free(generated);
4444
4545 // Parse the generated Zig code and render it in the canonical format
46 var tree = try std.zig.Ast.parse(gpa, generated, .zig);
46 var tree = try std.zig.Ast.parse(gpa, generated, .zig, .{});
4747 defer tree.deinit(gpa);
4848
4949 if (tree.errors.len != 0) {
tools/gen_spirv_spec.zig+1-1
......@@ -116,7 +116,7 @@ pub fn main(init: std.process.Init) !void {
116116 try allocating.writer.writeByte(0);
117117 const output = allocating.written()[0 .. allocating.written().len - 1 :0];
118118
119 var tree = try std.zig.Ast.parse(arena, output, .zig);
119 var tree = try std.zig.Ast.parse(arena, output, .zig, .{});
120120
121121 if (tree.errors.len != 0) {
122122 try std.zig.printAstErrorsToStderr(arena, io, tree, "", .auto);