authorgravatar for mason@anthropicstudios.comMason Remaley <mason@anthropicstudios.com> 2025-08-25 06:03:08-10:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-08-25 18:03:08+02:00
log5a0cf217756491169579b301a676a655b04f489b
tree5aee6a6ebf78125c47f657ba76fc34eacad56b40
parent37f4bee92a78fa4543d723b834a1570e2dd38a13
signaturebadge-check Signed by PGP key B5690EEEBB952194

Adds non allocating alternatives to ZON parse functions (#22916)

* Adds "flat" alternatives to zon.parse.from* that don't support pointers * Fixes documentation * Removes flat postfix from non allocating functions, adds alloc to others * Stops using alloc variant in tests where not needed

1 files changed, 192 insertions(+), 96 deletions(-)

lib/std/zon/parse.zig+192-96
......@@ -1,11 +1,12 @@
1//! The simplest way to parse ZON at runtime is to use `fromSlice`. If you need to parse ZON at
2//! compile time, you may use `@import`.
1//! The simplest way to parse ZON at runtime is to use `fromSlice`/`fromSliceAlloc`.
2//!
3//! Note that if you need to parse ZON at compile time, you may use `@import`.
34//!
45//! Parsing from individual Zoir nodes is also available:
5//! * `fromZoir`
6//! * `fromZoirNode`
6//! * `fromZoir`/`fromZoirAlloc`
7//! * `fromZoirNode`/`fromZoirNodeAlloc`
78//!
8//! For lower level control, it is possible to operate on `std.zig.Zoir` directly.
9//! For lower level control over parsing, see `std.zig.Zoir`.
910
1011const std = @import("std");
1112const builtin = @import("builtin");
......@@ -254,7 +255,25 @@ pub const Diagnostics = struct {
254255///
255256/// When the parser returns `error.ParseZon`, it will also store a human readable explanation in
256257/// `diag` if non null. If diag is not null, it must be initialized to `.{}`.
258///
259/// Asserts at compile time that the result type doesn't contain pointers. As such, the result
260/// doesn't need to be freed.
261///
262/// An allocator is still required for temporary allocations made during parsing.
257263pub fn fromSlice(
264 T: type,
265 gpa: Allocator,
266 source: [:0]const u8,
267 diag: ?*Diagnostics,
268 options: Options,
269) error{ OutOfMemory, ParseZon }!T {
270 comptime assert(!requiresAllocator(T));
271 return fromSliceAlloc(T, gpa, source, diag, options);
272}
273
274/// Like `fromSlice`, but the result may contain pointers. To automatically free the result, see
275/// `free`.
276pub fn fromSliceAlloc(
258277 /// The type to deserialize into. May not be or contain any of the following types:
259278 /// * Any comptime-only type, except in a comptime field
260279 /// * `type`
......@@ -285,11 +304,35 @@ pub fn fromSlice(
285304 defer if (diag == null) zoir.deinit(gpa);
286305
287306 if (diag) |s| s.* = .{};
288 return fromZoir(T, gpa, ast, zoir, diag, options);
307 return fromZoirAlloc(T, gpa, ast, zoir, diag, options);
289308}
290309
291310/// Like `fromSlice`, but operates on `Zoir` instead of ZON source.
292311pub fn fromZoir(
312 T: type,
313 ast: Ast,
314 zoir: Zoir,
315 diag: ?*Diagnostics,
316 options: Options,
317) error{ParseZon}!T {
318 comptime assert(!requiresAllocator(T));
319 var buf: [0]u8 = .{};
320 var failing_allocator = std.heap.FixedBufferAllocator.init(&buf);
321 return fromZoirAlloc(
322 T,
323 failing_allocator.allocator(),
324 ast,
325 zoir,
326 diag,
327 options,
328 ) catch |err| switch (err) {
329 error.OutOfMemory => unreachable, // Checked by comptime assertion above
330 else => |e| return e,
331 };
332}
333
334/// Like `fromSliceAlloc`, but operates on `Zoir` instead of ZON source.
335pub fn fromZoirAlloc(
293336 T: type,
294337 gpa: Allocator,
295338 ast: Ast,
......@@ -297,11 +340,37 @@ pub fn fromZoir(
297340 diag: ?*Diagnostics,
298341 options: Options,
299342) error{ OutOfMemory, ParseZon }!T {
300 return fromZoirNode(T, gpa, ast, zoir, .root, diag, options);
343 return fromZoirNodeAlloc(T, gpa, ast, zoir, .root, diag, options);
301344}
302345
303/// Like `fromZoir`, but the parse starts on `node` instead of root.
346/// Like `fromZoir`, but the parse starts at `node` instead of root.
304347pub fn fromZoirNode(
348 T: type,
349 ast: Ast,
350 zoir: Zoir,
351 node: Zoir.Node.Index,
352 diag: ?*Diagnostics,
353 options: Options,
354) error{ParseZon}!T {
355 comptime assert(!requiresAllocator(T));
356 var buf: [0]u8 = .{};
357 var failing_allocator = std.heap.FixedBufferAllocator.init(&buf);
358 return fromZoirNodeAlloc(
359 T,
360 failing_allocator.allocator(),
361 ast,
362 zoir,
363 node,
364 diag,
365 options,
366 ) catch |err| switch (err) {
367 error.OutOfMemory => unreachable, // Checked by comptime assertion above
368 else => |e| return e,
369 };
370}
371
372/// Like `fromZoirAlloc`, but the parse starts at `node` instead of root.
373pub fn fromZoirNodeAlloc(
305374 T: type,
306375 gpa: Allocator,
307376 ast: Ast,
......@@ -1321,7 +1390,7 @@ test "std.zon failure/oom formatting" {
13211390 });
13221391 var diag: Diagnostics = .{};
13231392 defer diag.deinit(gpa);
1324 try std.testing.expectError(error.OutOfMemory, fromSlice(
1393 try std.testing.expectError(error.OutOfMemory, fromSliceAlloc(
13251394 []const u8,
13261395 failing_allocator.allocator(),
13271396 "\"foo\"",
......@@ -1331,7 +1400,7 @@ test "std.zon failure/oom formatting" {
13311400 try std.testing.expectFmt("", "{f}", .{diag});
13321401}
13331402
1334test "std.zon fromSlice syntax error" {
1403test "std.zon fromSliceAlloc syntax error" {
13351404 try std.testing.expectError(
13361405 error.ParseZon,
13371406 fromSlice(u8, std.testing.allocator, ".{", null, .{}),
......@@ -1351,9 +1420,9 @@ test "std.zon optional" {
13511420
13521421 // Deep free
13531422 {
1354 const none = try fromSlice(?[]const u8, gpa, "null", null, .{});
1423 const none = try fromSliceAlloc(?[]const u8, gpa, "null", null, .{});
13551424 try std.testing.expect(none == null);
1356 const some = try fromSlice(?[]const u8, gpa, "\"foo\"", null, .{});
1425 const some = try fromSliceAlloc(?[]const u8, gpa, "\"foo\"", null, .{});
13571426 defer free(gpa, some);
13581427 try std.testing.expectEqualStrings("foo", some.?);
13591428 }
......@@ -1386,10 +1455,10 @@ test "std.zon unions" {
13861455 {
13871456 const Union = union(enum) { bar: []const u8, baz: bool };
13881457
1389 const noalloc = try fromSlice(Union, gpa, ".{.baz = false}", null, .{});
1458 const noalloc = try fromSliceAlloc(Union, gpa, ".{.baz = false}", null, .{});
13901459 try std.testing.expectEqual(Union{ .baz = false }, noalloc);
13911460
1392 const alloc = try fromSlice(Union, gpa, ".{.bar = \"qux\"}", null, .{});
1461 const alloc = try fromSliceAlloc(Union, gpa, ".{.bar = \"qux\"}", null, .{});
13931462 defer free(gpa, alloc);
13941463 try std.testing.expectEqualDeep(Union{ .bar = "qux" }, alloc);
13951464 }
......@@ -1401,7 +1470,7 @@ test "std.zon unions" {
14011470 defer diag.deinit(gpa);
14021471 try std.testing.expectError(
14031472 error.ParseZon,
1404 fromSlice(Union, gpa, ".{.z=2.5}", &diag, .{}),
1473 fromSliceAlloc(Union, gpa, ".{.z=2.5}", &diag, .{}),
14051474 );
14061475 try std.testing.expectFmt(
14071476 \\1:4: error: unexpected field 'z'
......@@ -1420,7 +1489,7 @@ test "std.zon unions" {
14201489 defer diag.deinit(gpa);
14211490 try std.testing.expectError(
14221491 error.ParseZon,
1423 fromSlice(Union, gpa, ".{.x=1}", &diag, .{}),
1492 fromSliceAlloc(Union, gpa, ".{.x=1}", &diag, .{}),
14241493 );
14251494 try std.testing.expectFmt("1:6: error: expected type 'void'\n", "{f}", .{diag});
14261495 }
......@@ -1432,7 +1501,7 @@ test "std.zon unions" {
14321501 defer diag.deinit(gpa);
14331502 try std.testing.expectError(
14341503 error.ParseZon,
1435 fromSlice(Union, gpa, ".{.x = 1.5, .y = true}", &diag, .{}),
1504 fromSliceAlloc(Union, gpa, ".{.x = 1.5, .y = true}", &diag, .{}),
14361505 );
14371506 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});
14381507 }
......@@ -1444,7 +1513,7 @@ test "std.zon unions" {
14441513 defer diag.deinit(gpa);
14451514 try std.testing.expectError(
14461515 error.ParseZon,
1447 fromSlice(Union, gpa, ".{}", &diag, .{}),
1516 fromSliceAlloc(Union, gpa, ".{}", &diag, .{}),
14481517 );
14491518 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});
14501519 }
......@@ -1454,7 +1523,7 @@ test "std.zon unions" {
14541523 const Union = union { x: void };
14551524 var diag: Diagnostics = .{};
14561525 defer diag.deinit(gpa);
1457 try std.testing.expectError(error.ParseZon, fromSlice(Union, gpa, ".x", &diag, .{}));
1526 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, gpa, ".x", &diag, .{}));
14581527 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});
14591528 }
14601529
......@@ -1463,7 +1532,7 @@ test "std.zon unions" {
14631532 const Union = union(enum) { x: void };
14641533 var diag: Diagnostics = .{};
14651534 defer diag.deinit(gpa);
1466 try std.testing.expectError(error.ParseZon, fromSlice(Union, gpa, ".y", &diag, .{}));
1535 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, gpa, ".y", &diag, .{}));
14671536 try std.testing.expectFmt(
14681537 \\1:2: error: unexpected field 'y'
14691538 \\1:2: note: supported: 'x'
......@@ -1479,7 +1548,7 @@ test "std.zon unions" {
14791548 const Union = union(enum) { x: f32 };
14801549 var diag: Diagnostics = .{};
14811550 defer diag.deinit(gpa);
1482 try std.testing.expectError(error.ParseZon, fromSlice(Union, gpa, ".x", &diag, .{}));
1551 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Union, gpa, ".x", &diag, .{}));
14831552 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{diag});
14841553 }
14851554}
......@@ -1511,7 +1580,7 @@ test "std.zon structs" {
15111580 {
15121581 const Foo = struct { bar: []const u8, baz: []const []const u8 };
15131582
1514 const parsed = try fromSlice(
1583 const parsed = try fromSliceAlloc(
15151584 Foo,
15161585 gpa,
15171586 ".{.bar = \"qux\", .baz = .{\"a\", \"b\"}}",
......@@ -1668,7 +1737,7 @@ test "std.zon structs" {
16681737 {
16691738 var diag: Diagnostics = .{};
16701739 defer diag.deinit(gpa);
1671 const parsed = fromSlice([]u8, gpa, "[]u8{1, 2, 3}", &diag, .{});
1740 const parsed = fromSliceAlloc([]u8, gpa, "[]u8{1, 2, 3}", &diag, .{});
16721741 try std.testing.expectError(error.ParseZon, parsed);
16731742 try std.testing.expectFmt(
16741743 \\1:1: error: types are not available in ZON
......@@ -1737,7 +1806,7 @@ test "std.zon tuples" {
17371806 // Deep free
17381807 {
17391808 const Tuple = struct { []const u8, []const u8 };
1740 const parsed = try fromSlice(Tuple, gpa, ".{\"hello\", \"world\"}", null, .{});
1809 const parsed = try fromSliceAlloc(Tuple, gpa, ".{\"hello\", \"world\"}", null, .{});
17411810 defer free(gpa, parsed);
17421811 try std.testing.expectEqualDeep(Tuple{ "hello", "world" }, parsed);
17431812 }
......@@ -1847,27 +1916,27 @@ test "std.zon arrays and slices" {
18471916
18481917 // Slice literals
18491918 {
1850 const zero = try fromSlice([]const u8, gpa, ".{}", null, .{});
1919 const zero = try fromSliceAlloc([]const u8, gpa, ".{}", null, .{});
18511920 defer free(gpa, zero);
18521921 try std.testing.expectEqualSlices(u8, @as([]const u8, &.{}), zero);
18531922
1854 const one = try fromSlice([]u8, gpa, ".{'a'}", null, .{});
1923 const one = try fromSliceAlloc([]u8, gpa, ".{'a'}", null, .{});
18551924 defer free(gpa, one);
18561925 try std.testing.expectEqualSlices(u8, &.{'a'}, one);
18571926
1858 const two = try fromSlice([]const u8, gpa, ".{'a', 'b'}", null, .{});
1927 const two = try fromSliceAlloc([]const u8, gpa, ".{'a', 'b'}", null, .{});
18591928 defer free(gpa, two);
18601929 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b' }, two);
18611930
1862 const two_comma = try fromSlice([]const u8, gpa, ".{'a', 'b',}", null, .{});
1931 const two_comma = try fromSliceAlloc([]const u8, gpa, ".{'a', 'b',}", null, .{});
18631932 defer free(gpa, two_comma);
18641933 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b' }, two_comma);
18651934
1866 const three = try fromSlice([]u8, gpa, ".{'a', 'b', 'c'}", null, .{});
1935 const three = try fromSliceAlloc([]u8, gpa, ".{'a', 'b', 'c'}", null, .{});
18671936 defer free(gpa, three);
18681937 try std.testing.expectEqualSlices(u8, &.{ 'a', 'b', 'c' }, three);
18691938
1870 const sentinel = try fromSlice([:'z']const u8, gpa, ".{'a', 'b', 'c'}", null, .{});
1939 const sentinel = try fromSliceAlloc([:'z']const u8, gpa, ".{'a', 'b', 'c'}", null, .{});
18711940 defer free(gpa, sentinel);
18721941 const expected_sentinel: [:'z']const u8 = &.{ 'a', 'b', 'c' };
18731942 try std.testing.expectEqualSlices(u8, expected_sentinel, sentinel);
......@@ -1878,7 +1947,7 @@ test "std.zon arrays and slices" {
18781947 {
18791948 // Arrays
18801949 {
1881 const parsed = try fromSlice([1][]const u8, gpa, ".{\"abc\"}", null, .{});
1950 const parsed = try fromSliceAlloc([1][]const u8, gpa, ".{\"abc\"}", null, .{});
18821951 defer free(gpa, parsed);
18831952 const expected: [1][]const u8 = .{"abc"};
18841953 try std.testing.expectEqualDeep(expected, parsed);
......@@ -1886,7 +1955,7 @@ test "std.zon arrays and slices" {
18861955
18871956 // Slice literals
18881957 {
1889 const parsed = try fromSlice([]const []const u8, gpa, ".{\"abc\"}", null, .{});
1958 const parsed = try fromSliceAlloc([]const []const u8, gpa, ".{\"abc\"}", null, .{});
18901959 defer free(gpa, parsed);
18911960 const expected: []const []const u8 = &.{"abc"};
18921961 try std.testing.expectEqualDeep(expected, parsed);
......@@ -1905,7 +1974,7 @@ test "std.zon arrays and slices" {
19051974
19061975 // Slice literals
19071976 {
1908 const sentinel = try fromSlice([:2]align(4) u8, gpa, ".{1}", null, .{});
1977 const sentinel = try fromSliceAlloc([:2]align(4) u8, gpa, ".{1}", null, .{});
19091978 defer free(gpa, sentinel);
19101979 try std.testing.expectEqual(@as(usize, 1), sentinel.len);
19111980 try std.testing.expectEqual(@as(u8, 1), sentinel[0]);
......@@ -1992,7 +2061,7 @@ test "std.zon arrays and slices" {
19922061 defer diag.deinit(gpa);
19932062 try std.testing.expectError(
19942063 error.ParseZon,
1995 fromSlice([]bool, gpa, ".{'a', 'b', 'c'}", &diag, .{}),
2064 fromSliceAlloc([]bool, gpa, ".{'a', 'b', 'c'}", &diag, .{}),
19962065 );
19972066 try std.testing.expectFmt("1:3: error: expected type 'bool'\n", "{f}", .{diag});
19982067 }
......@@ -2017,7 +2086,7 @@ test "std.zon arrays and slices" {
20172086 defer diag.deinit(gpa);
20182087 try std.testing.expectError(
20192088 error.ParseZon,
2020 fromSlice([]u8, gpa, "'a'", &diag, .{}),
2089 fromSliceAlloc([]u8, gpa, "'a'", &diag, .{}),
20212090 );
20222091 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
20232092 }
......@@ -2029,7 +2098,7 @@ test "std.zon arrays and slices" {
20292098 defer diag.deinit(gpa);
20302099 try std.testing.expectError(
20312100 error.ParseZon,
2032 fromSlice([]u8, gpa, " &.{'a', 'b', 'c'}", &diag, .{}),
2101 fromSliceAlloc([]u8, gpa, " &.{'a', 'b', 'c'}", &diag, .{}),
20332102 );
20342103 try std.testing.expectFmt(
20352104 "1:3: error: pointers are not available in ZON\n",
......@@ -2044,21 +2113,21 @@ test "std.zon string literal" {
20442113
20452114 // Basic string literal
20462115 {
2047 const parsed = try fromSlice([]const u8, gpa, "\"abc\"", null, .{});
2116 const parsed = try fromSliceAlloc([]const u8, gpa, "\"abc\"", null, .{});
20482117 defer free(gpa, parsed);
20492118 try std.testing.expectEqualStrings(@as([]const u8, "abc"), parsed);
20502119 }
20512120
20522121 // String literal with escape characters
20532122 {
2054 const parsed = try fromSlice([]const u8, gpa, "\"ab\\nc\"", null, .{});
2123 const parsed = try fromSliceAlloc([]const u8, gpa, "\"ab\\nc\"", null, .{});
20552124 defer free(gpa, parsed);
20562125 try std.testing.expectEqualStrings(@as([]const u8, "ab\nc"), parsed);
20572126 }
20582127
20592128 // String literal with embedded null
20602129 {
2061 const parsed = try fromSlice([]const u8, gpa, "\"ab\\x00c\"", null, .{});
2130 const parsed = try fromSliceAlloc([]const u8, gpa, "\"ab\\x00c\"", null, .{});
20622131 defer free(gpa, parsed);
20632132 try std.testing.expectEqualStrings(@as([]const u8, "ab\x00c"), parsed);
20642133 }
......@@ -2070,7 +2139,7 @@ test "std.zon string literal" {
20702139 defer diag.deinit(gpa);
20712140 try std.testing.expectError(
20722141 error.ParseZon,
2073 fromSlice([]u8, gpa, "\"abcd\"", &diag, .{}),
2142 fromSliceAlloc([]u8, gpa, "\"abcd\"", &diag, .{}),
20742143 );
20752144 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
20762145 }
......@@ -2080,7 +2149,7 @@ test "std.zon string literal" {
20802149 defer diag.deinit(gpa);
20812150 try std.testing.expectError(
20822151 error.ParseZon,
2083 fromSlice([]u8, gpa, "\\\\abcd", &diag, .{}),
2152 fromSliceAlloc([]u8, gpa, "\\\\abcd", &diag, .{}),
20842153 );
20852154 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
20862155 }
......@@ -2116,7 +2185,7 @@ test "std.zon string literal" {
21162185 // Zero terminated slices
21172186 {
21182187 {
2119 const parsed: [:0]const u8 = try fromSlice(
2188 const parsed: [:0]const u8 = try fromSliceAlloc(
21202189 [:0]const u8,
21212190 gpa,
21222191 "\"abc\"",
......@@ -2129,7 +2198,7 @@ test "std.zon string literal" {
21292198 }
21302199
21312200 {
2132 const parsed: [:0]const u8 = try fromSlice(
2201 const parsed: [:0]const u8 = try fromSliceAlloc(
21332202 [:0]const u8,
21342203 gpa,
21352204 "\\\\abc",
......@@ -2149,7 +2218,7 @@ test "std.zon string literal" {
21492218 defer diag.deinit(gpa);
21502219 try std.testing.expectError(
21512220 error.ParseZon,
2152 fromSlice([:1]const u8, gpa, "\"foo\"", &diag, .{}),
2221 fromSliceAlloc([:1]const u8, gpa, "\"foo\"", &diag, .{}),
21532222 );
21542223 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
21552224 }
......@@ -2159,7 +2228,7 @@ test "std.zon string literal" {
21592228 defer diag.deinit(gpa);
21602229 try std.testing.expectError(
21612230 error.ParseZon,
2162 fromSlice([:1]const u8, gpa, "\\\\foo", &diag, .{}),
2231 fromSliceAlloc([:1]const u8, gpa, "\\\\foo", &diag, .{}),
21632232 );
21642233 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
21652234 }
......@@ -2171,7 +2240,7 @@ test "std.zon string literal" {
21712240 defer diag.deinit(gpa);
21722241 try std.testing.expectError(
21732242 error.ParseZon,
2174 fromSlice([]const u8, gpa, "true", &diag, .{}),
2243 fromSliceAlloc([]const u8, gpa, "true", &diag, .{}),
21752244 );
21762245 try std.testing.expectFmt("1:1: error: expected string\n", "{f}", .{diag});
21772246 }
......@@ -2182,7 +2251,7 @@ test "std.zon string literal" {
21822251 defer diag.deinit(gpa);
21832252 try std.testing.expectError(
21842253 error.ParseZon,
2185 fromSlice([]const u8, gpa, ".{false}", &diag, .{}),
2254 fromSliceAlloc([]const u8, gpa, ".{false}", &diag, .{}),
21862255 );
21872256 try std.testing.expectFmt("1:3: error: expected type 'u8'\n", "{f}", .{diag});
21882257 }
......@@ -2193,7 +2262,7 @@ test "std.zon string literal" {
21932262 defer diag.deinit(gpa);
21942263 try std.testing.expectError(
21952264 error.ParseZon,
2196 fromSlice([]const i8, gpa, "\"\\a\"", &diag, .{}),
2265 fromSliceAlloc([]const i8, gpa, "\"\\a\"", &diag, .{}),
21972266 );
21982267 try std.testing.expectFmt("1:3: error: invalid escape character: 'a'\n", "{f}", .{diag});
21992268 }
......@@ -2205,7 +2274,7 @@ test "std.zon string literal" {
22052274 defer diag.deinit(gpa);
22062275 try std.testing.expectError(
22072276 error.ParseZon,
2208 fromSlice([]const i8, gpa, "\"a\"", &diag, .{}),
2277 fromSliceAlloc([]const i8, gpa, "\"a\"", &diag, .{}),
22092278 );
22102279 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
22112280 }
......@@ -2215,7 +2284,7 @@ test "std.zon string literal" {
22152284 defer diag.deinit(gpa);
22162285 try std.testing.expectError(
22172286 error.ParseZon,
2218 fromSlice([]const i8, gpa, "\\\\a", &diag, .{}),
2287 fromSliceAlloc([]const i8, gpa, "\\\\a", &diag, .{}),
22192288 );
22202289 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
22212290 }
......@@ -2228,7 +2297,7 @@ test "std.zon string literal" {
22282297 defer diag.deinit(gpa);
22292298 try std.testing.expectError(
22302299 error.ParseZon,
2231 fromSlice([]align(2) const u8, gpa, "\"abc\"", &diag, .{}),
2300 fromSliceAlloc([]align(2) const u8, gpa, "\"abc\"", &diag, .{}),
22322301 );
22332302 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
22342303 }
......@@ -2238,7 +2307,7 @@ test "std.zon string literal" {
22382307 defer diag.deinit(gpa);
22392308 try std.testing.expectError(
22402309 error.ParseZon,
2241 fromSlice([]align(2) const u8, gpa, "\\\\abc", &diag, .{}),
2310 fromSliceAlloc([]align(2) const u8, gpa, "\\\\abc", &diag, .{}),
22422311 );
22432312 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{diag});
22442313 }
......@@ -2253,7 +2322,7 @@ test "std.zon string literal" {
22532322 message2: String,
22542323 message3: String,
22552324 };
2256 const parsed = try fromSlice(S, gpa,
2325 const parsed = try fromSliceAlloc(S, gpa,
22572326 \\.{
22582327 \\ .message =
22592328 \\ \\hello, world!
......@@ -2909,7 +2978,7 @@ test "std.zon free on error" {
29092978 y: []const u8,
29102979 z: bool,
29112980 };
2912 try std.testing.expectError(error.ParseZon, fromSlice(Struct, std.testing.allocator,
2981 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, std.testing.allocator,
29132982 \\.{
29142983 \\ .x = "hello",
29152984 \\ .y = "world",
......@@ -2925,7 +2994,7 @@ test "std.zon free on error" {
29252994 []const u8,
29262995 bool,
29272996 };
2928 try std.testing.expectError(error.ParseZon, fromSlice(Struct, std.testing.allocator,
2997 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, std.testing.allocator,
29292998 \\.{
29302999 \\ "hello",
29313000 \\ "world",
......@@ -2940,7 +3009,7 @@ test "std.zon free on error" {
29403009 x: []const u8,
29413010 y: bool,
29423011 };
2943 try std.testing.expectError(error.ParseZon, fromSlice(Struct, std.testing.allocator,
3012 try std.testing.expectError(error.ParseZon, fromSliceAlloc(Struct, std.testing.allocator,
29443013 \\.{
29453014 \\ .x = "hello",
29463015 \\}
......@@ -2949,7 +3018,7 @@ test "std.zon free on error" {
29493018
29503019 // Test freeing partially allocated arrays
29513020 {
2952 try std.testing.expectError(error.ParseZon, fromSlice(
3021 try std.testing.expectError(error.ParseZon, fromSliceAlloc(
29533022 [3][]const u8,
29543023 std.testing.allocator,
29553024 \\.{
......@@ -2965,7 +3034,7 @@ test "std.zon free on error" {
29653034
29663035 // Test freeing partially allocated slices
29673036 {
2968 try std.testing.expectError(error.ParseZon, fromSlice(
3037 try std.testing.expectError(error.ParseZon, fromSliceAlloc(
29693038 [][]const u8,
29703039 std.testing.allocator,
29713040 \\.{
......@@ -2989,7 +3058,7 @@ test "std.zon free on error" {
29893058 // We can also parse types that can't be freed if it's impossible for an error to occur after
29903059 // the allocation, as is the case here.
29913060 {
2992 const result = try fromSlice(
3061 const result = try fromSliceAlloc(
29933062 union { x: []const u8 },
29943063 std.testing.allocator,
29953064 ".{ .x = \"foo\" }",
......@@ -3008,7 +3077,7 @@ test "std.zon free on error" {
30083077 union { x: []const u8 },
30093078 bool,
30103079 };
3011 const result = try fromSlice(
3080 const result = try fromSliceAlloc(
30123081 S,
30133082 std.testing.allocator,
30143083 ".{ .{ .x = \"foo\" }, true }",
......@@ -3026,7 +3095,7 @@ test "std.zon free on error" {
30263095 a: union { x: []const u8 },
30273096 b: bool,
30283097 };
3029 const result = try fromSlice(
3098 const result = try fromSliceAlloc(
30303099 S,
30313100 std.testing.allocator,
30323101 ".{ .a = .{ .x = \"foo\" }, .b = true }",
......@@ -3043,7 +3112,7 @@ test "std.zon free on error" {
30433112 // Again but for arrays.
30443113 {
30453114 const S = [2]union { x: []const u8 };
3046 const result = try fromSlice(
3115 const result = try fromSliceAlloc(
30473116 S,
30483117 std.testing.allocator,
30493118 ".{ .{ .x = \"foo\" }, .{ .x = \"bar\" } }",
......@@ -3061,7 +3130,7 @@ test "std.zon free on error" {
30613130 // Again but for slices.
30623131 {
30633132 const S = []union { x: []const u8 };
3064 const result = try fromSlice(
3133 const result = try fromSliceAlloc(
30653134 S,
30663135 std.testing.allocator,
30673136 ".{ .{ .x = \"foo\" }, .{ .x = \"bar\" } }",
......@@ -3114,9 +3183,9 @@ test "std.zon vector" {
31143183 {
31153184 try std.testing.expectEqual(
31163185 @Vector(0, *const u8){},
3117 try fromSlice(@Vector(0, *const u8), gpa, ".{}", null, .{}),
3186 try fromSliceAlloc(@Vector(0, *const u8), gpa, ".{}", null, .{}),
31183187 );
3119 const pointers = try fromSlice(@Vector(3, *const u8), gpa, ".{2, 4, 6}", null, .{});
3188 const pointers = try fromSliceAlloc(@Vector(3, *const u8), gpa, ".{2, 4, 6}", null, .{});
31203189 defer free(gpa, pointers);
31213190 try std.testing.expectEqualDeep(@Vector(3, *const u8){ &2, &4, &6 }, pointers);
31223191 }
......@@ -3124,9 +3193,9 @@ test "std.zon vector" {
31243193 {
31253194 try std.testing.expectEqual(
31263195 @Vector(0, ?*const u8){},
3127 try fromSlice(@Vector(0, ?*const u8), gpa, ".{}", null, .{}),
3196 try fromSliceAlloc(@Vector(0, ?*const u8), gpa, ".{}", null, .{}),
31283197 );
3129 const pointers = try fromSlice(@Vector(3, ?*const u8), gpa, ".{2, null, 6}", null, .{});
3198 const pointers = try fromSliceAlloc(@Vector(3, ?*const u8), gpa, ".{2, null, 6}", null, .{});
31303199 defer free(gpa, pointers);
31313200 try std.testing.expectEqualDeep(@Vector(3, ?*const u8){ &2, null, &6 }, pointers);
31323201 }
......@@ -3193,7 +3262,7 @@ test "std.zon vector" {
31933262 defer diag.deinit(gpa);
31943263 try std.testing.expectError(
31953264 error.ParseZon,
3196 fromSlice(@Vector(3, *u8), gpa, ".{1, true, 3}", &diag, .{}),
3265 fromSliceAlloc(@Vector(3, *u8), gpa, ".{1, true, 3}", &diag, .{}),
31973266 );
31983267 try std.testing.expectFmt("1:6: error: expected type 'u8'\n", "{f}", .{diag});
31993268 }
......@@ -3204,77 +3273,77 @@ test "std.zon add pointers" {
32043273
32053274 // Primitive with varying levels of pointers
32063275 {
3207 const result = try fromSlice(*u32, gpa, "10", null, .{});
3276 const result = try fromSliceAlloc(*u32, gpa, "10", null, .{});
32083277 defer free(gpa, result);
32093278 try std.testing.expectEqual(@as(u32, 10), result.*);
32103279 }
32113280
32123281 {
3213 const result = try fromSlice(**u32, gpa, "10", null, .{});
3282 const result = try fromSliceAlloc(**u32, gpa, "10", null, .{});
32143283 defer free(gpa, result);
32153284 try std.testing.expectEqual(@as(u32, 10), result.*.*);
32163285 }
32173286
32183287 {
3219 const result = try fromSlice(***u32, gpa, "10", null, .{});
3288 const result = try fromSliceAlloc(***u32, gpa, "10", null, .{});
32203289 defer free(gpa, result);
32213290 try std.testing.expectEqual(@as(u32, 10), result.*.*.*);
32223291 }
32233292
32243293 // Primitive optional with varying levels of pointers
32253294 {
3226 const some = try fromSlice(?*u32, gpa, "10", null, .{});
3295 const some = try fromSliceAlloc(?*u32, gpa, "10", null, .{});
32273296 defer free(gpa, some);
32283297 try std.testing.expectEqual(@as(u32, 10), some.?.*);
32293298
3230 const none = try fromSlice(?*u32, gpa, "null", null, .{});
3299 const none = try fromSliceAlloc(?*u32, gpa, "null", null, .{});
32313300 defer free(gpa, none);
32323301 try std.testing.expectEqual(null, none);
32333302 }
32343303
32353304 {
3236 const some = try fromSlice(*?u32, gpa, "10", null, .{});
3305 const some = try fromSliceAlloc(*?u32, gpa, "10", null, .{});
32373306 defer free(gpa, some);
32383307 try std.testing.expectEqual(@as(u32, 10), some.*.?);
32393308
3240 const none = try fromSlice(*?u32, gpa, "null", null, .{});
3309 const none = try fromSliceAlloc(*?u32, gpa, "null", null, .{});
32413310 defer free(gpa, none);
32423311 try std.testing.expectEqual(null, none.*);
32433312 }
32443313
32453314 {
3246 const some = try fromSlice(?**u32, gpa, "10", null, .{});
3315 const some = try fromSliceAlloc(?**u32, gpa, "10", null, .{});
32473316 defer free(gpa, some);
32483317 try std.testing.expectEqual(@as(u32, 10), some.?.*.*);
32493318
3250 const none = try fromSlice(?**u32, gpa, "null", null, .{});
3319 const none = try fromSliceAlloc(?**u32, gpa, "null", null, .{});
32513320 defer free(gpa, none);
32523321 try std.testing.expectEqual(null, none);
32533322 }
32543323
32553324 {
3256 const some = try fromSlice(*?*u32, gpa, "10", null, .{});
3325 const some = try fromSliceAlloc(*?*u32, gpa, "10", null, .{});
32573326 defer free(gpa, some);
32583327 try std.testing.expectEqual(@as(u32, 10), some.*.?.*);
32593328
3260 const none = try fromSlice(*?*u32, gpa, "null", null, .{});
3329 const none = try fromSliceAlloc(*?*u32, gpa, "null", null, .{});
32613330 defer free(gpa, none);
32623331 try std.testing.expectEqual(null, none.*);
32633332 }
32643333
32653334 {
3266 const some = try fromSlice(**?u32, gpa, "10", null, .{});
3335 const some = try fromSliceAlloc(**?u32, gpa, "10", null, .{});
32673336 defer free(gpa, some);
32683337 try std.testing.expectEqual(@as(u32, 10), some.*.*.?);
32693338
3270 const none = try fromSlice(**?u32, gpa, "null", null, .{});
3339 const none = try fromSliceAlloc(**?u32, gpa, "null", null, .{});
32713340 defer free(gpa, none);
32723341 try std.testing.expectEqual(null, none.*.*);
32733342 }
32743343
32753344 // Pointer to an array
32763345 {
3277 const result = try fromSlice(*[3]u8, gpa, ".{ 1, 2, 3 }", null, .{});
3346 const result = try fromSliceAlloc(*[3]u8, gpa, ".{ 1, 2, 3 }", null, .{});
32783347 defer free(gpa, result);
32793348 try std.testing.expectEqual([3]u8{ 1, 2, 3 }, result.*);
32803349 }
......@@ -3297,7 +3366,7 @@ test "std.zon add pointers" {
32973366 .f2 = &null,
32983367 };
32993368
3300 const found = try fromSlice(?*Outer, gpa,
3369 const found = try fromSliceAlloc(?*Outer, gpa,
33013370 \\.{
33023371 \\ .f1 = .{
33033372 \\ .f1 = null,
......@@ -3317,7 +3386,7 @@ test "std.zon add pointers" {
33173386 defer diag.deinit(gpa);
33183387 try std.testing.expectError(
33193388 error.ParseZon,
3320 fromSlice(*const ?*const u8, gpa, "true", &diag, .{}),
3389 fromSliceAlloc(*const ?*const u8, gpa, "true", &diag, .{}),
33213390 );
33223391 try std.testing.expectFmt("1:1: error: expected type '?u8'\n", "{f}", .{diag});
33233392 }
......@@ -3327,7 +3396,7 @@ test "std.zon add pointers" {
33273396 defer diag.deinit(gpa);
33283397 try std.testing.expectError(
33293398 error.ParseZon,
3330 fromSlice(*const ?*const f32, gpa, "true", &diag, .{}),
3399 fromSliceAlloc(*const ?*const f32, gpa, "true", &diag, .{}),
33313400 );
33323401 try std.testing.expectFmt("1:1: error: expected type '?f32'\n", "{f}", .{diag});
33333402 }
......@@ -3337,7 +3406,7 @@ test "std.zon add pointers" {
33373406 defer diag.deinit(gpa);
33383407 try std.testing.expectError(
33393408 error.ParseZon,
3340 fromSlice(*const ?*const @Vector(3, u8), gpa, "true", &diag, .{}),
3409 fromSliceAlloc(*const ?*const @Vector(3, u8), gpa, "true", &diag, .{}),
33413410 );
33423411 try std.testing.expectFmt("1:1: error: expected type '?@Vector(3, u8)'\n", "{f}", .{diag});
33433412 }
......@@ -3347,7 +3416,7 @@ test "std.zon add pointers" {
33473416 defer diag.deinit(gpa);
33483417 try std.testing.expectError(
33493418 error.ParseZon,
3350 fromSlice(*const ?*const bool, gpa, "10", &diag, .{}),
3419 fromSliceAlloc(*const ?*const bool, gpa, "10", &diag, .{}),
33513420 );
33523421 try std.testing.expectFmt("1:1: error: expected type '?bool'\n", "{f}", .{diag});
33533422 }
......@@ -3357,7 +3426,7 @@ test "std.zon add pointers" {
33573426 defer diag.deinit(gpa);
33583427 try std.testing.expectError(
33593428 error.ParseZon,
3360 fromSlice(*const ?*const struct { a: i32 }, gpa, "true", &diag, .{}),
3429 fromSliceAlloc(*const ?*const struct { a: i32 }, gpa, "true", &diag, .{}),
33613430 );
33623431 try std.testing.expectFmt("1:1: error: expected optional struct\n", "{f}", .{diag});
33633432 }
......@@ -3367,7 +3436,7 @@ test "std.zon add pointers" {
33673436 defer diag.deinit(gpa);
33683437 try std.testing.expectError(
33693438 error.ParseZon,
3370 fromSlice(*const ?*const struct { i32 }, gpa, "true", &diag, .{}),
3439 fromSliceAlloc(*const ?*const struct { i32 }, gpa, "true", &diag, .{}),
33713440 );
33723441 try std.testing.expectFmt("1:1: error: expected optional tuple\n", "{f}", .{diag});
33733442 }
......@@ -3377,7 +3446,7 @@ test "std.zon add pointers" {
33773446 defer diag.deinit(gpa);
33783447 try std.testing.expectError(
33793448 error.ParseZon,
3380 fromSlice(*const ?*const union { x: void }, gpa, "true", &diag, .{}),
3449 fromSliceAlloc(*const ?*const union { x: void }, gpa, "true", &diag, .{}),
33813450 );
33823451 try std.testing.expectFmt("1:1: error: expected optional union\n", "{f}", .{diag});
33833452 }
......@@ -3387,7 +3456,7 @@ test "std.zon add pointers" {
33873456 defer diag.deinit(gpa);
33883457 try std.testing.expectError(
33893458 error.ParseZon,
3390 fromSlice(*const ?*const [3]u8, gpa, "true", &diag, .{}),
3459 fromSliceAlloc(*const ?*const [3]u8, gpa, "true", &diag, .{}),
33913460 );
33923461 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
33933462 }
......@@ -3397,7 +3466,7 @@ test "std.zon add pointers" {
33973466 defer diag.deinit(gpa);
33983467 try std.testing.expectError(
33993468 error.ParseZon,
3400 fromSlice(?[3]u8, gpa, "true", &diag, .{}),
3469 fromSliceAlloc(?[3]u8, gpa, "true", &diag, .{}),
34013470 );
34023471 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
34033472 }
......@@ -3407,7 +3476,7 @@ test "std.zon add pointers" {
34073476 defer diag.deinit(gpa);
34083477 try std.testing.expectError(
34093478 error.ParseZon,
3410 fromSlice(*const ?*const []u8, gpa, "true", &diag, .{}),
3479 fromSliceAlloc(*const ?*const []u8, gpa, "true", &diag, .{}),
34113480 );
34123481 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
34133482 }
......@@ -3417,7 +3486,7 @@ test "std.zon add pointers" {
34173486 defer diag.deinit(gpa);
34183487 try std.testing.expectError(
34193488 error.ParseZon,
3420 fromSlice(?[]u8, gpa, "true", &diag, .{}),
3489 fromSliceAlloc(?[]u8, gpa, "true", &diag, .{}),
34213490 );
34223491 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{diag});
34233492 }
......@@ -3427,7 +3496,7 @@ test "std.zon add pointers" {
34273496 defer diag.deinit(gpa);
34283497 try std.testing.expectError(
34293498 error.ParseZon,
3430 fromSlice(*const ?*const []const u8, gpa, "true", &diag, .{}),
3499 fromSliceAlloc(*const ?*const []const u8, gpa, "true", &diag, .{}),
34313500 );
34323501 try std.testing.expectFmt("1:1: error: expected optional string\n", "{f}", .{diag});
34333502 }
......@@ -3437,7 +3506,7 @@ test "std.zon add pointers" {
34373506 defer diag.deinit(gpa);
34383507 try std.testing.expectError(
34393508 error.ParseZon,
3440 fromSlice(*const ?*const enum { foo }, gpa, "true", &diag, .{}),
3509 fromSliceAlloc(*const ?*const enum { foo }, gpa, "true", &diag, .{}),
34413510 );
34423511 try std.testing.expectFmt("1:1: error: expected optional enum literal\n", "{f}", .{diag});
34433512 }
......@@ -3466,3 +3535,30 @@ test "std.zon stop on node" {
34663535 try std.testing.expectEqual(Zoir.Node{ .float_literal = 1.23 }, result.get(diag.zoir));
34673536 }
34683537}
3538
3539test "std.zon no alloc" {
3540 const gpa = std.testing.allocator;
3541
3542 try std.testing.expectEqual(
3543 [3]u8{ 1, 2, 3 },
3544 try fromSlice([3]u8, gpa, ".{ 1, 2, 3 }", null, .{}),
3545 );
3546
3547 const Nested = struct { u8, u8, struct { u8, u8 } };
3548
3549 var ast = try std.zig.Ast.parse(gpa, ".{ 1, 2, .{ 3, 4 } }", .zon);
3550 defer ast.deinit(gpa);
3551
3552 var zoir = try ZonGen.generate(gpa, ast, .{ .parse_str_lits = false });
3553 defer zoir.deinit(gpa);
3554
3555 try std.testing.expectEqual(
3556 Nested{ 1, 2, .{ 3, 4 } },
3557 try fromZoir(Nested, ast, zoir, null, .{}),
3558 );
3559
3560 try std.testing.expectEqual(
3561 Nested{ 1, 2, .{ 3, 4 } },
3562 try fromZoirNode(Nested, ast, zoir, .root, null, .{}),
3563 );
3564}