authorgravatar for mason@gamesbymason.comMason Remaley <mason@gamesbymason.com> 2026-08-07 15:01:20-07:00
committergravatar for mason@gamesbymason.comMason Remaley <mason@gamesbymason.com> 2026-09-26 12:35:38-07:00
loge4a7988fec0d53e5f48a1701aeebacf192198203
treef8f440343b8841c3c3d3a5c81c6c9e8cfc669e14
parentab52406e0c5598b651b11f3f7f93ad5ddb875896

Add a path to Errors formatter, add `log` and `fatal` helpers


1 files changed, 440 insertions(+), 277 deletions(-)

lib/std/zon/parse.zig+440-277
...@@ -7,6 +7,7 @@...@@ -7,6 +7,7 @@
7//! parsing, see `std.zig.ZonGen`. For importing ZON at compile time, use `@import`.7//! parsing, see `std.zig.ZonGen`. For importing ZON at compile time, use `@import`.
88
9const std = @import("std");9const std = @import("std");
10const builtin = @import("builtin");
10const Allocator = std.mem.Allocator;11const Allocator = std.mem.Allocator;
11const Ast = std.zig.Ast;12const Ast = std.zig.Ast;
12const Zoir = std.zig.Zoir;13const Zoir = std.zig.Zoir;
...@@ -39,7 +40,7 @@ pub const Error = struct {...@@ -39,7 +40,7 @@ pub const Error = struct {
39 notes: []Note,40 notes: []Note,
40 };41 };
4142
42 fn init(ast: *const Ast, options: InitOptions) @This() {43 fn init(ast: *const Ast, options: InitOptions) Error {
43 return .{44 return .{
44 .msg = options.msg,45 .msg = options.msg,
45 .loc = astLoc(ast, options.token, options.node_or_offset),46 .loc = astLoc(ast, options.token, options.node_or_offset),
...@@ -90,40 +91,110 @@ pub const Error = struct {...@@ -90,40 +91,110 @@ pub const Error = struct {
90 };91 };
91};92};
9293
93/// Errors encountered while parsing ZON. Consider logging this using the default format method to94/// Errors encountered while parsing ZON. See `log` and `fatal` for reporting errors to the user.
94/// provide users with feedback on the failure.
95pub const Errors = struct {95pub const Errors = struct {
96 arena: Allocator,96 arena: Allocator,
97 list: std.ArrayList(Error),97 list: std.ArrayList(Error),
9898
99 pub fn init(arena: Allocator) @This() {99 pub fn init(arena: Allocator) Errors {
100 return .{100 return .{
101 .arena = arena,101 .arena = arena,
102 .list = .empty,102 .list = .empty,
103 };103 };
104 }104 }
105105
106 pub fn format(self: *const @This(), w: *std.Io.Writer) std.Io.Writer.Error!void {106 /// Log the failure with `std.log.err`.
107 for (self.list.items) |e| {107 pub fn log(
108 try w.print("{d}:{d}: error: {s}\n", .{108 self: *const Errors,
109 e.loc.line + 1,109 path: []const u8,
110 e.loc.column + 1,110 err: error{ OutOfMemory, ParseZon },
111 e.msg,111 ) void {
112 });112 std.log.err("{s}: {}\n{f}", .{ path, err, self.fmt(path) });
113 }
113114
114 for (e.notes) |note| {115 test log {
115 try w.print("{d}:{d}: note: {s}\n", .{116 const gpa = std.testing.allocator;
116 note.loc.line + 1,117 var arena_allocator: ArenaAllocator = .init(gpa);
117 note.loc.column + 1,118 defer arena_allocator.deinit();
118 note.msg,119 const arena = arena_allocator.allocator();
119 });120
120 }121 const MyType = struct {
121 }122 foo: u32,
123 bar: u32,
124 };
125
126 const errors: Errors = .init(arena);
127 const parsed: MyType = fromSlice(MyType, .{
128 .gpa = gpa,
129 .source = ".{ .foo = 1, .bar = 2 }",
130 .errors = null,
131 }) catch |err| b: {
132 errors.log("input.zon", err);
133 break :b .{ .foo = 0, .bar = 0 };
134 };
135 _ = parsed;
136 }
137
138 /// Log the failure with `std.log.err`, and then terminate the process with exit code 1.
139 pub fn fatal(
140 self: *const Errors,
141 path: []const u8,
142 err: error{ OutOfMemory, ParseZon },
143 ) noreturn {
144 std.process.fatal("{s}: {}\n{f}", .{ path, err, self.fmt(path) });
145 }
146
147 test fatal {
148 const gpa = std.testing.allocator;
149 var arena_allocator: ArenaAllocator = .init(gpa);
150 defer arena_allocator.deinit();
151 const arena = arena_allocator.allocator();
152
153 const MyType = struct {
154 foo: u32,
155 bar: u32,
156 };
157
158 const errors: Errors = .init(arena);
159 const parsed = fromSlice(MyType, .{
160 .gpa = gpa,
161 .source = ".{ .foo = 1, .bar = 2 }",
162 .errors = null,
163 }) catch |err| errors.fatal("input.zon", err);
164 _ = parsed;
122 }165 }
123166
124 pub fn clear(self: *@This()) void {167 pub fn fmt(self: *const Errors, path: []const u8) Formatter {
125 self.errors.clearRetainingCapacity();168 return .{
169 .path = path,
170 .errors = self.list.items,
171 };
126 }172 }
173
174 pub const Formatter = struct {
175 path: []const u8,
176 errors: []const Error,
177
178 pub fn format(self: *const @This(), w: *std.Io.Writer) std.Io.Writer.Error!void {
179 for (self.errors) |e| {
180 try w.print("{s}:", .{self.path});
181 try w.print("{d}:{d}: error: {s}\n", .{
182 e.loc.line + 1,
183 e.loc.column + 1,
184 e.msg,
185 });
186
187 for (e.notes) |note| {
188 try w.print("{s}:", .{self.path});
189 try w.print("{d}:{d}: note: {s}\n", .{
190 note.loc.line + 1,
191 note.loc.column + 1,
192 note.msg,
193 });
194 }
195 }
196 }
197 };
127};198};
128199
129pub const FromSliceOptions = struct {200pub const FromSliceOptions = struct {
...@@ -432,7 +503,7 @@ const Parser = struct {...@@ -432,7 +503,7 @@ const Parser = struct {
432 const ParseExprError = error{ ParseZon, OutOfMemory };503 const ParseExprError = error{ ParseZon, OutOfMemory };
433504
434 fn parseExprInto(505 fn parseExprInto(
435 self: *@This(),506 self: *Parser,
436 node: Zoir.Node.Index,507 node: Zoir.Node.Index,
437 out: anytype,508 out: anytype,
438 initialized: bool,509 initialized: bool,
...@@ -519,7 +590,7 @@ const Parser = struct {...@@ -519,7 +590,7 @@ const Parser = struct {
519 /// example, `**?**u8` becomes `?u8`, and types that involve user specified type names are just590 /// example, `**?**u8` becomes `?u8`, and types that involve user specified type names are just
520 /// referred to by the type of container.591 /// referred to by the type of container.
521 fn failExpectedType(592 fn failExpectedType(
522 self: @This(),593 self: Parser,
523 T: type,594 T: type,
524 node: Zoir.Node.Index,595 node: Zoir.Node.Index,
525 ) error{ ParseZon, OutOfMemory } {596 ) error{ ParseZon, OutOfMemory } {
...@@ -528,7 +599,7 @@ const Parser = struct {...@@ -528,7 +599,7 @@ const Parser = struct {
528 }599 }
529600
530 fn failExpectedTypeInner(601 fn failExpectedTypeInner(
531 self: @This(),602 self: Parser,
532 T: type,603 T: type,
533 opt: bool,604 opt: bool,
534 node: Zoir.Node.Index,605 node: Zoir.Node.Index,
...@@ -598,7 +669,7 @@ const Parser = struct {...@@ -598,7 +669,7 @@ const Parser = struct {
598 }669 }
599 }670 }
600671
601 fn parseBool(self: @This(), node: Zoir.Node.Index) !bool {672 fn parseBool(self: Parser, node: Zoir.Node.Index) !bool {
602 switch (node.get(self.zoir)) {673 switch (node.get(self.zoir)) {
603 .true => return true,674 .true => return true,
604 .false => return false,675 .false => return false,
...@@ -606,7 +677,7 @@ const Parser = struct {...@@ -606,7 +677,7 @@ const Parser = struct {
606 }677 }
607 }678 }
608679
609 fn parseInt(self: @This(), T: type, node: Zoir.Node.Index) !T {680 fn parseInt(self: Parser, T: type, node: Zoir.Node.Index) !T {
610 switch (node.get(self.zoir)) {681 switch (node.get(self.zoir)) {
611 .int_literal => |int| switch (int) {682 .int_literal => |int| switch (int) {
612 .small => |val| return std.math.cast(T, val) orelse683 .small => |val| return std.math.cast(T, val) orelse
...@@ -623,7 +694,7 @@ const Parser = struct {...@@ -623,7 +694,7 @@ const Parser = struct {
623 }694 }
624 }695 }
625696
626 fn parseFloat(self: @This(), T: type, node: Zoir.Node.Index) !T {697 fn parseFloat(self: Parser, T: type, node: Zoir.Node.Index) !T {
627 switch (node.get(self.zoir)) {698 switch (node.get(self.zoir)) {
628 .int_literal => |int| switch (int) {699 .int_literal => |int| switch (int) {
629 .small => |val| return @floatFromInt(val),700 .small => |val| return @floatFromInt(val),
...@@ -638,7 +709,7 @@ const Parser = struct {...@@ -638,7 +709,7 @@ const Parser = struct {
638 }709 }
639 }710 }
640711
641 fn parseEnumLiteral(self: @This(), T: type, node: Zoir.Node.Index) !T {712 fn parseEnumLiteral(self: Parser, T: type, node: Zoir.Node.Index) !T {
642 switch (node.get(self.zoir)) {713 switch (node.get(self.zoir)) {
643 .enum_literal => |field_name| {714 .enum_literal => |field_name| {
644 // Create a comptime string map for the enum fields715 // Create a comptime string map for the enum fields
...@@ -658,7 +729,7 @@ const Parser = struct {...@@ -658,7 +729,7 @@ const Parser = struct {
658 }729 }
659 }730 }
660731
661 fn parseSlicePointer(self: *@This(), T: type, node: Zoir.Node.Index) ParseExprInnerError!T {732 fn parseSlicePointer(self: *Parser, T: type, node: Zoir.Node.Index) ParseExprInnerError!T {
662 switch (node.get(self.zoir)) {733 switch (node.get(self.zoir)) {
663 .string_literal => return self.parseString(T, node),734 .string_literal => return self.parseString(T, node),
664 .array_literal => |nodes| return self.parseSlice(T, nodes),735 .array_literal => |nodes| return self.parseSlice(T, nodes),
...@@ -667,7 +738,7 @@ const Parser = struct {...@@ -667,7 +738,7 @@ const Parser = struct {
667 }738 }
668 }739 }
669740
670 fn parseString(self: *@This(), T: type, node: Zoir.Node.Index) ParseExprInnerError!T {741 fn parseString(self: *Parser, T: type, node: Zoir.Node.Index) ParseExprInnerError!T {
671 const ast_node = node.getAstNode(self.zoir);742 const ast_node = node.getAstNode(self.zoir);
672 const pointer = @typeInfo(T).pointer;743 const pointer = @typeInfo(T).pointer;
673 var size_hint = ZonGen.strLitSizeHint(self.ast, ast_node);744 var size_hint = ZonGen.strLitSizeHint(self.ast, ast_node);
...@@ -702,7 +773,7 @@ const Parser = struct {...@@ -702,7 +773,7 @@ const Parser = struct {
702 }773 }
703 }774 }
704775
705 fn parseSlice(self: *@This(), T: type, nodes: Zoir.Node.Index.Range) !T {776 fn parseSlice(self: *Parser, T: type, nodes: Zoir.Node.Index.Range) !T {
706 const pointer = @typeInfo(T).pointer;777 const pointer = @typeInfo(T).pointer;
707778
708 // Make sure we're working with a slice779 // Make sure we're working with a slice
...@@ -727,7 +798,7 @@ const Parser = struct {...@@ -727,7 +798,7 @@ const Parser = struct {
727 return slice;798 return slice;
728 }799 }
729800
730 fn parseArrayInto(self: *@This(), node: Zoir.Node.Index, out: anytype) !void {801 fn parseArrayInto(self: *Parser, node: Zoir.Node.Index, out: anytype) !void {
731 const nodes: Zoir.Node.Index.Range = switch (node.get(self.zoir)) {802 const nodes: Zoir.Node.Index.Range = switch (node.get(self.zoir)) {
732 .array_literal => |nodes| nodes,803 .array_literal => |nodes| nodes,
733 .empty_literal => .{ .start = node, .len = 0 },804 .empty_literal => .{ .start = node, .len = 0 },
...@@ -761,7 +832,7 @@ const Parser = struct {...@@ -761,7 +832,7 @@ const Parser = struct {
761 }832 }
762 }833 }
763834
764 fn parseVectorInto(self: *@This(), node: Zoir.Node.Index, out: anytype) !void {835 fn parseVectorInto(self: *Parser, node: Zoir.Node.Index, out: anytype) !void {
765 const vector = @typeInfo(@TypeOf(out.*)).vector;836 const vector = @typeInfo(@TypeOf(out.*)).vector;
766 var array: [vector.len]vector.child = undefined;837 var array: [vector.len]vector.child = undefined;
767 try self.parseArrayInto(node, &array);838 try self.parseArrayInto(node, &array);
...@@ -769,7 +840,7 @@ const Parser = struct {...@@ -769,7 +840,7 @@ const Parser = struct {
769 }840 }
770841
771 fn parseStructInto(842 fn parseStructInto(
772 self: *@This(),843 self: *Parser,
773 node: Zoir.Node.Index,844 node: Zoir.Node.Index,
774 out: anytype,845 out: anytype,
775 initialized: bool,846 initialized: bool,
...@@ -843,7 +914,7 @@ const Parser = struct {...@@ -843,7 +914,7 @@ const Parser = struct {
843 }914 }
844 }915 }
845916
846 fn parseTupleInto(self: *@This(), node: Zoir.Node.Index, out: anytype) !void {917 fn parseTupleInto(self: *Parser, node: Zoir.Node.Index, out: anytype) !void {
847 const nodes: Zoir.Node.Index.Range = switch (node.get(self.zoir)) {918 const nodes: Zoir.Node.Index.Range = switch (node.get(self.zoir)) {
848 .array_literal => |nodes| nodes,919 .array_literal => |nodes| nodes,
849 .empty_literal => .{ .start = node, .len = 0 },920 .empty_literal => .{ .start = node, .len = 0 },
...@@ -879,7 +950,7 @@ const Parser = struct {...@@ -879,7 +950,7 @@ const Parser = struct {
879 }950 }
880951
881 fn parseUnionInto(952 fn parseUnionInto(
882 self: *@This(),953 self: *Parser,
883 node: Zoir.Node.Index,954 node: Zoir.Node.Index,
884 out: anytype,955 out: anytype,
885 initialized: bool,956 initialized: bool,
...@@ -981,7 +1052,7 @@ const Parser = struct {...@@ -981,7 +1052,7 @@ const Parser = struct {
981 }1052 }
9821053
983 fn failTokenFmt(1054 fn failTokenFmt(
984 self: @This(),1055 self: Parser,
985 token: Ast.TokenIndex,1056 token: Ast.TokenIndex,
986 offset: u32,1057 offset: u32,
987 comptime fmt: []const u8,1058 comptime fmt: []const u8,
...@@ -992,7 +1063,7 @@ const Parser = struct {...@@ -992,7 +1063,7 @@ const Parser = struct {
992 }1063 }
9931064
994 fn failTokenFmtNote(1065 fn failTokenFmtNote(
995 self: @This(),1066 self: Parser,
996 token: Ast.TokenIndex,1067 token: Ast.TokenIndex,
997 offset: u32,1068 offset: u32,
998 comptime fmt: []const u8,1069 comptime fmt: []const u8,
...@@ -1011,7 +1082,7 @@ const Parser = struct {...@@ -1011,7 +1082,7 @@ const Parser = struct {
1011 }1082 }
10121083
1013 fn failNodeFmt(1084 fn failNodeFmt(
1014 self: @This(),1085 self: Parser,
1015 node: Zoir.Node.Index,1086 node: Zoir.Node.Index,
1016 comptime fmt: []const u8,1087 comptime fmt: []const u8,
1017 args: anytype,1088 args: anytype,
...@@ -1022,7 +1093,7 @@ const Parser = struct {...@@ -1022,7 +1093,7 @@ const Parser = struct {
1022 }1093 }
10231094
1024 fn failToken(1095 fn failToken(
1025 self: @This(),1096 self: Parser,
1026 failure: Error,1097 failure: Error,
1027 ) error{ OutOfMemory, ParseZon } {1098 ) error{ OutOfMemory, ParseZon } {
1028 @branchHint(.cold);1099 @branchHint(.cold);
...@@ -1031,7 +1102,7 @@ const Parser = struct {...@@ -1031,7 +1102,7 @@ const Parser = struct {
1031 }1102 }
10321103
1033 fn failNode(1104 fn failNode(
1034 self: @This(),1105 self: Parser,
1035 node: Zoir.Node.Index,1106 node: Zoir.Node.Index,
1036 msg: []const u8,1107 msg: []const u8,
1037 ) error{ OutOfMemory, ParseZon } {1108 ) error{ OutOfMemory, ParseZon } {
...@@ -1046,7 +1117,7 @@ const Parser = struct {...@@ -1046,7 +1117,7 @@ const Parser = struct {
1046 }1117 }
10471118
1048 fn failCannotRepresent(1119 fn failCannotRepresent(
1049 self: @This(),1120 self: Parser,
1050 T: type,1121 T: type,
1051 node: Zoir.Node.Index,1122 node: Zoir.Node.Index,
1052 ) error{ OutOfMemory, ParseZon } {1123 ) error{ OutOfMemory, ParseZon } {
...@@ -1055,7 +1126,7 @@ const Parser = struct {...@@ -1055,7 +1126,7 @@ const Parser = struct {
1055 }1126 }
10561127
1057 fn failUnexpected(1128 fn failUnexpected(
1058 self: @This(),1129 self: Parser,
1059 T: type,1130 T: type,
1060 item_kind: []const u8,1131 item_kind: []const u8,
1061 node: Zoir.Node.Index,1132 node: Zoir.Node.Index,
...@@ -1111,7 +1182,7 @@ const Parser = struct {...@@ -1111,7 +1182,7 @@ const Parser = struct {
1111 // the value matched, but doing so doesn't seem to support any real use cases1182 // the value matched, but doing so doesn't seem to support any real use cases
1112 // so isn't worth the complexity at the moment.1183 // so isn't worth the complexity at the moment.
1113 fn failComptimeField(1184 fn failComptimeField(
1114 self: @This(),1185 self: Parser,
1115 node: Zoir.Node.Index,1186 node: Zoir.Node.Index,
1116 field: usize,1187 field: usize,
1117 ) error{ OutOfMemory, ParseZon } {1188 ) error{ OutOfMemory, ParseZon } {
...@@ -1306,7 +1377,10 @@ test "std.zon ast errors" {...@@ -1306,7 +1377,10 @@ test "std.zon ast errors" {
1306 .errors = &errors,1377 .errors = &errors,
1307 }),1378 }),
1308 );1379 );
1309 try std.testing.expectFmt("1:13: error: expected ',' after initializer\n", "{f}", .{errors});1380 try std.testing.expectFmt(
1381 \\input.zon:1:13: error: expected ',' after initializer
1382 \\
1383 , "{f}", .{errors.fmt("input.zon")});
1310}1384}
13111385
1312test "std.zon comments" {1386test "std.zon comments" {
...@@ -1336,11 +1410,7 @@ test "std.zon comments" {...@@ -1336,11 +1410,7 @@ test "std.zon comments" {
1336 ,1410 ,
1337 .errors = &errors,1411 .errors = &errors,
1338 }));1412 }));
1339 try std.testing.expectFmt(1413 try std.testing.expectFmt("input.zon:1:1: error: expected expression, found 'a document comment'\n", "{f}", .{errors.fmt("input.zon")});
1340 "1:1: error: expected expression, found 'a document comment'\n",
1341 "{f}",
1342 .{errors},
1343 );
1344 }1414 }
1345}1415}
13461416
...@@ -1356,7 +1426,9 @@ test "std.zon failure/oom formatting" {...@@ -1356,7 +1426,9 @@ test "std.zon failure/oom formatting" {
1356 .source = "\"foo\"",1426 .source = "\"foo\"",
1357 .errors = &errors,1427 .errors = &errors,
1358 }));1428 }));
1359 try std.testing.expectFmt("", "{f}", .{errors});1429 try std.testing.expectFmt(
1430 \\
1431 , "{f}", .{errors.fmt("input.zon")});
1360}1432}
13611433
1362test "std.zon fromSliceAlloc syntax error" {1434test "std.zon fromSliceAlloc syntax error" {
...@@ -1497,13 +1569,10 @@ test "std.zon unions" {...@@ -1497,13 +1569,10 @@ test "std.zon unions" {
1497 }),1569 }),
1498 );1570 );
1499 try std.testing.expectFmt(1571 try std.testing.expectFmt(
1500 \\1:4: error: unexpected field 'z'1572 \\input.zon:1:4: error: unexpected field 'z'
1501 \\1:4: note: supported: 'x', 'y'1573 \\input.zon:1:4: note: supported: 'x', 'y'
1502 \\1574 \\
1503 ,1575 , "{f}", .{errors.fmt("input.zon")});
1504 "{f}",
1505 .{errors},
1506 );
1507 }1576 }
15081577
1509 // Explicit void field1578 // Explicit void field
...@@ -1519,7 +1588,10 @@ test "std.zon unions" {...@@ -1519,7 +1588,10 @@ test "std.zon unions" {
1519 .errors = &errors,1588 .errors = &errors,
1520 }),1589 }),
1521 );1590 );
1522 try std.testing.expectFmt("1:6: error: expected type 'void'\n", "{f}", .{errors});1591 try std.testing.expectFmt(
1592 \\input.zon:1:6: error: expected type 'void'
1593 \\
1594 , "{f}", .{errors.fmt("input.zon")});
1523 }1595 }
15241596
1525 // Extra field1597 // Extra field
...@@ -1535,7 +1607,10 @@ test "std.zon unions" {...@@ -1535,7 +1607,10 @@ test "std.zon unions" {
1535 .errors = &errors,1607 .errors = &errors,
1536 }),1608 }),
1537 );1609 );
1538 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{errors});1610 try std.testing.expectFmt(
1611 \\input.zon:1:2: error: expected union
1612 \\
1613 , "{f}", .{errors.fmt("input.zon")});
1539 }1614 }
15401615
1541 // No fields1616 // No fields
...@@ -1551,7 +1626,10 @@ test "std.zon unions" {...@@ -1551,7 +1626,10 @@ test "std.zon unions" {
1551 .errors = &errors,1626 .errors = &errors,
1552 }),1627 }),
1553 );1628 );
1554 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{errors});1629 try std.testing.expectFmt(
1630 \\input.zon:1:2: error: expected union
1631 \\
1632 , "{f}", .{errors.fmt("input.zon")});
1555 }1633 }
15561634
1557 // Enum literals cannot coerce into untagged unions1635 // Enum literals cannot coerce into untagged unions
...@@ -1564,7 +1642,10 @@ test "std.zon unions" {...@@ -1564,7 +1642,10 @@ test "std.zon unions" {
1564 .source = ".x",1642 .source = ".x",
1565 .errors = &errors,1643 .errors = &errors,
1566 }));1644 }));
1567 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{errors});1645 try std.testing.expectFmt(
1646 \\input.zon:1:2: error: expected union
1647 \\
1648 , "{f}", .{errors.fmt("input.zon")});
1568 }1649 }
15691650
1570 // Unknown field for enum literal coercion1651 // Unknown field for enum literal coercion
...@@ -1578,13 +1659,10 @@ test "std.zon unions" {...@@ -1578,13 +1659,10 @@ test "std.zon unions" {
1578 .errors = &errors,1659 .errors = &errors,
1579 }));1660 }));
1580 try std.testing.expectFmt(1661 try std.testing.expectFmt(
1581 \\1:2: error: unexpected field 'y'1662 \\input.zon:1:2: error: unexpected field 'y'
1582 \\1:2: note: supported: 'x'1663 \\input.zon:1:2: note: supported: 'x'
1583 \\1664 \\
1584 ,1665 , "{f}", .{errors.fmt("input.zon")});
1585 "{f}",
1586 .{errors},
1587 );
1588 }1666 }
15891667
1590 // Non void field for enum literal coercion1668 // Non void field for enum literal coercion
...@@ -1597,7 +1675,10 @@ test "std.zon unions" {...@@ -1597,7 +1675,10 @@ test "std.zon unions" {
1597 .source = ".x",1675 .source = ".x",
1598 .errors = &errors,1676 .errors = &errors,
1599 }));1677 }));
1600 try std.testing.expectFmt("1:2: error: expected union\n", "{f}", .{errors});1678 try std.testing.expectFmt(
1679 \\input.zon:1:2: error: expected union
1680 \\
1681 , "{f}", .{errors.fmt("input.zon")});
1601 }1682 }
1602}1683}
16031684
...@@ -1669,13 +1750,10 @@ test "std.zon structs" {...@@ -1669,13 +1750,10 @@ test "std.zon structs" {
1669 }),1750 }),
1670 );1751 );
1671 try std.testing.expectFmt(1752 try std.testing.expectFmt(
1672 \\1:12: error: unexpected field 'z'1753 \\input.zon:1:12: error: unexpected field 'z'
1673 \\1:12: note: supported: 'x', 'y'1754 \\input.zon:1:12: note: supported: 'x', 'y'
1674 \\1755 \\
1675 ,1756 , "{f}", .{errors.fmt("input.zon")});
1676 "{f}",
1677 .{errors},
1678 );
1679 }1757 }
16801758
1681 // Duplicate field1759 // Duplicate field
...@@ -1691,10 +1769,10 @@ test "std.zon structs" {...@@ -1691,10 +1769,10 @@ test "std.zon structs" {
1691 }),1769 }),
1692 );1770 );
1693 try std.testing.expectFmt(1771 try std.testing.expectFmt(
1694 \\1:4: error: duplicate struct field name1772 \\input.zon:1:4: error: duplicate struct field name
1695 \\1:12: note: duplicate name here1773 \\input.zon:1:12: note: duplicate name here
1696 \\1774 \\
1697 , "{f}", .{errors});1775 , "{f}", .{errors.fmt("input.zon")});
1698 }1776 }
16991777
1700 // Ignore unknown fields1778 // Ignore unknown fields
...@@ -1722,10 +1800,10 @@ test "std.zon structs" {...@@ -1722,10 +1800,10 @@ test "std.zon structs" {
1722 }),1800 }),
1723 );1801 );
1724 try std.testing.expectFmt(1802 try std.testing.expectFmt(
1725 \\1:4: error: unexpected field 'x'1803 \\input.zon:1:4: error: unexpected field 'x'
1726 \\1:4: note: none expected1804 \\input.zon:1:4: note: none expected
1727 \\1805 \\
1728 , "{f}", .{errors});1806 , "{f}", .{errors.fmt("input.zon")});
1729 }1807 }
17301808
1731 // Missing field1809 // Missing field
...@@ -1740,7 +1818,10 @@ test "std.zon structs" {...@@ -1740,7 +1818,10 @@ test "std.zon structs" {
1740 .errors = &errors,1818 .errors = &errors,
1741 }),1819 }),
1742 );1820 );
1743 try std.testing.expectFmt("1:2: error: missing required field y\n", "{f}", .{errors});1821 try std.testing.expectFmt(
1822 \\input.zon:1:2: error: missing required field y
1823 \\
1824 , "{f}", .{errors.fmt("input.zon")});
1744 }1825 }
17451826
1746 // Default field1827 // Default field
...@@ -1776,9 +1857,9 @@ test "std.zon structs" {...@@ -1776,9 +1857,9 @@ test "std.zon structs" {
1776 });1857 });
1777 try std.testing.expectError(error.ParseZon, parsed);1858 try std.testing.expectError(error.ParseZon, parsed);
1778 try std.testing.expectFmt(1859 try std.testing.expectFmt(
1779 \\1:18: error: cannot initialize comptime field1860 \\input.zon:1:18: error: cannot initialize comptime field
1780 \\1861 \\
1781 , "{f}", .{errors});1862 , "{f}", .{errors.fmt("input.zon")});
1782 }1863 }
17831864
1784 // Enum field (regression test, we were previously getting the field name in an1865 // Enum field (regression test, we were previously getting the field name in an
...@@ -1816,10 +1897,10 @@ test "std.zon structs" {...@@ -1816,10 +1897,10 @@ test "std.zon structs" {
1816 });1897 });
1817 try std.testing.expectError(error.ParseZon, parsed);1898 try std.testing.expectError(error.ParseZon, parsed);
1818 try std.testing.expectFmt(1899 try std.testing.expectFmt(
1819 \\1:1: error: types are not available in ZON1900 \\input.zon:1:1: error: types are not available in ZON
1820 \\1:1: note: replace the type with '.'1901 \\input.zon:1:1: note: replace the type with '.'
1821 \\1902 \\
1822 , "{f}", .{errors});1903 , "{f}", .{errors.fmt("input.zon")});
1823 }1904 }
18241905
1825 // Arrays1906 // Arrays
...@@ -1832,10 +1913,10 @@ test "std.zon structs" {...@@ -1832,10 +1913,10 @@ test "std.zon structs" {
1832 });1913 });
1833 try std.testing.expectError(error.ParseZon, parsed);1914 try std.testing.expectError(error.ParseZon, parsed);
1834 try std.testing.expectFmt(1915 try std.testing.expectFmt(
1835 \\1:1: error: types are not available in ZON1916 \\input.zon:1:1: error: types are not available in ZON
1836 \\1:1: note: replace the type with '.'1917 \\input.zon:1:1: note: replace the type with '.'
1837 \\1918 \\
1838 , "{f}", .{errors});1919 , "{f}", .{errors.fmt("input.zon")});
1839 }1920 }
18401921
1841 // Slices1922 // Slices
...@@ -1849,10 +1930,10 @@ test "std.zon structs" {...@@ -1849,10 +1930,10 @@ test "std.zon structs" {
1849 });1930 });
1850 try std.testing.expectError(error.ParseZon, parsed);1931 try std.testing.expectError(error.ParseZon, parsed);
1851 try std.testing.expectFmt(1932 try std.testing.expectFmt(
1852 \\1:1: error: types are not available in ZON1933 \\input.zon:1:1: error: types are not available in ZON
1853 \\1:1: note: replace the type with '.'1934 \\input.zon:1:1: note: replace the type with '.'
1854 \\1935 \\
1855 , "{f}", .{errors});1936 , "{f}", .{errors.fmt("input.zon")});
1856 }1937 }
18571938
1858 // Tuples1939 // Tuples
...@@ -1865,10 +1946,10 @@ test "std.zon structs" {...@@ -1865,10 +1946,10 @@ test "std.zon structs" {
1865 });1946 });
1866 try std.testing.expectError(error.ParseZon, parsed);1947 try std.testing.expectError(error.ParseZon, parsed);
1867 try std.testing.expectFmt(1948 try std.testing.expectFmt(
1868 \\1:1: error: types are not available in ZON1949 \\input.zon:1:1: error: types are not available in ZON
1869 \\1:1: note: replace the type with '.'1950 \\input.zon:1:1: note: replace the type with '.'
1870 \\1951 \\
1871 , "{f}", .{errors});1952 , "{f}", .{errors.fmt("input.zon")});
1872 }1953 }
18731954
1874 // Nested1955 // Nested
...@@ -1881,10 +1962,10 @@ test "std.zon structs" {...@@ -1881,10 +1962,10 @@ test "std.zon structs" {
1881 });1962 });
1882 try std.testing.expectError(error.ParseZon, parsed);1963 try std.testing.expectError(error.ParseZon, parsed);
1883 try std.testing.expectFmt(1964 try std.testing.expectFmt(
1884 \\1:9: error: types are not available in ZON1965 \\input.zon:1:9: error: types are not available in ZON
1885 \\1:9: note: replace the type with '.'1966 \\input.zon:1:9: note: replace the type with '.'
1886 \\1967 \\
1887 , "{f}", .{errors});1968 , "{f}", .{errors.fmt("input.zon")});
1888 }1969 }
1889 }1970 }
1890}1971}
...@@ -1955,7 +2036,10 @@ test "std.zon tuples" {...@@ -1955,7 +2036,10 @@ test "std.zon tuples" {
1955 .errors = &errors,2036 .errors = &errors,
1956 }),2037 }),
1957 );2038 );
1958 try std.testing.expectFmt("1:14: error: index 2 outside of tuple length 2\n", "{f}", .{errors});2039 try std.testing.expectFmt(
2040 \\input.zon:1:14: error: index 2 outside of tuple length 2
2041 \\
2042 , "{f}", .{errors.fmt("input.zon")});
1959 }2043 }
19602044
1961 // Extra field2045 // Extra field
...@@ -1971,10 +2055,9 @@ test "std.zon tuples" {...@@ -1971,10 +2055,9 @@ test "std.zon tuples" {
1971 }),2055 }),
1972 );2056 );
1973 try std.testing.expectFmt(2057 try std.testing.expectFmt(
1974 "1:2: error: missing tuple field with index 1\n",2058 \\input.zon:1:2: error: missing tuple field with index 1
1975 "{f}",2059 \\
1976 .{errors},2060 , "{f}", .{errors.fmt("input.zon")});
1977 );
1978 }2061 }
19792062
1980 // Tuple with unexpected field names2063 // Tuple with unexpected field names
...@@ -1989,7 +2072,7 @@ test "std.zon tuples" {...@@ -1989,7 +2072,7 @@ test "std.zon tuples" {
1989 .errors = &errors,2072 .errors = &errors,
1990 }),2073 }),
1991 );2074 );
1992 try std.testing.expectFmt("1:2: error: expected tuple\n", "{f}", .{errors});2075 try std.testing.expectFmt("input.zon:1:2: error: expected tuple\n", "{f}", .{errors.fmt("input.zon")});
1993 }2076 }
19942077
1995 // Struct with missing field names2078 // Struct with missing field names
...@@ -2004,7 +2087,10 @@ test "std.zon tuples" {...@@ -2004,7 +2087,10 @@ test "std.zon tuples" {
2004 .errors = &errors,2087 .errors = &errors,
2005 }),2088 }),
2006 );2089 );
2007 try std.testing.expectFmt("1:2: error: expected struct\n", "{f}", .{errors});2090 try std.testing.expectFmt(
2091 \\input.zon:1:2: error: expected struct
2092 \\
2093 , "{f}", .{errors.fmt("input.zon")});
2008 }2094 }
20092095
2010 // Comptime field2096 // Comptime field
...@@ -2029,14 +2115,16 @@ test "std.zon tuples" {...@@ -2029,14 +2115,16 @@ test "std.zon tuples" {
2029 });2115 });
2030 try std.testing.expectError(error.ParseZon, parsed);2116 try std.testing.expectError(error.ParseZon, parsed);
2031 try std.testing.expectFmt(2117 try std.testing.expectFmt(
2032 \\1:9: error: cannot initialize comptime field2118 \\input.zon:1:9: error: cannot initialize comptime field
2033 \\2119 \\
2034 , "{f}", .{errors});2120 , "{f}", .{errors.fmt("input.zon")});
2035 }2121 }
2036}2122}
20372123
2038// Test sizes 0 to 3 since small sizes get parsed differently2124// Test sizes 0 to 3 since small sizes get parsed differently
2039test "std.zon arrays and slices" {2125test "std.zon arrays and slices" {
2126 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/20881
2127
2040 const gpa = std.testing.allocator;2128 const gpa = std.testing.allocator;
2041 var arena_allocator: ArenaAllocator = .init(gpa);2129 var arena_allocator: ArenaAllocator = .init(gpa);
2042 defer arena_allocator.deinit();2130 defer arena_allocator.deinit();
...@@ -2210,10 +2298,9 @@ test "std.zon arrays and slices" {...@@ -2210,10 +2298,9 @@ test "std.zon arrays and slices" {
2210 }),2298 }),
2211 );2299 );
2212 try std.testing.expectFmt(2300 try std.testing.expectFmt(
2213 "1:3: error: index 0 outside of array of length 0\n",2301 \\input.zon:1:3: error: index 0 outside of array of length 0
2214 "{f}",2302 \\
2215 .{errors},2303 , "{f}", .{errors.fmt("input.zon")});
2216 );
2217 }2304 }
22182305
2219 // Expect 1 find 22306 // Expect 1 find 2
...@@ -2228,10 +2315,9 @@ test "std.zon arrays and slices" {...@@ -2228,10 +2315,9 @@ test "std.zon arrays and slices" {
2228 }),2315 }),
2229 );2316 );
2230 try std.testing.expectFmt(2317 try std.testing.expectFmt(
2231 "1:8: error: index 1 outside of array of length 1\n",2318 \\input.zon:1:8: error: index 1 outside of array of length 1
2232 "{f}",2319 \\
2233 .{errors},2320 , "{f}", .{errors.fmt("input.zon")});
2234 );
2235 }2321 }
22362322
2237 // Expect 2 find 12323 // Expect 2 find 1
...@@ -2246,10 +2332,9 @@ test "std.zon arrays and slices" {...@@ -2246,10 +2332,9 @@ test "std.zon arrays and slices" {
2246 }),2332 }),
2247 );2333 );
2248 try std.testing.expectFmt(2334 try std.testing.expectFmt(
2249 "1:2: error: expected 2 array elements; found 1\n",2335 \\input.zon:1:2: error: expected 2 array elements; found 1
2250 "{f}",2336 \\
2251 .{errors},2337 , "{f}", .{errors.fmt("input.zon")});
2252 );
2253 }2338 }
22542339
2255 // Expect 3 find 02340 // Expect 3 find 0
...@@ -2263,11 +2348,7 @@ test "std.zon arrays and slices" {...@@ -2263,11 +2348,7 @@ test "std.zon arrays and slices" {
2263 .errors = &errors,2348 .errors = &errors,
2264 }),2349 }),
2265 );2350 );
2266 try std.testing.expectFmt(2351 try std.testing.expectFmt("input.zon:1:2: error: expected 3 array elements; found 0\n", "{f}", .{errors.fmt("input.zon")});
2267 "1:2: error: expected 3 array elements; found 0\n",
2268 "{f}",
2269 .{errors},
2270 );
2271 }2352 }
22722353
2273 // Wrong inner type2354 // Wrong inner type
...@@ -2283,7 +2364,10 @@ test "std.zon arrays and slices" {...@@ -2283,7 +2364,10 @@ test "std.zon arrays and slices" {
2283 .errors = &errors,2364 .errors = &errors,
2284 }),2365 }),
2285 );2366 );
2286 try std.testing.expectFmt("1:3: error: expected type 'bool'\n", "{f}", .{errors});2367 try std.testing.expectFmt(
2368 \\input.zon:1:3: error: expected type 'bool'
2369 \\
2370 , "{f}", .{errors.fmt("input.zon")});
2287 }2371 }
22882372
2289 // Slice2373 // Slice
...@@ -2298,7 +2382,7 @@ test "std.zon arrays and slices" {...@@ -2298,7 +2382,7 @@ test "std.zon arrays and slices" {
2298 .errors = &errors,2382 .errors = &errors,
2299 }),2383 }),
2300 );2384 );
2301 try std.testing.expectFmt("1:3: error: expected type 'bool'\n", "{f}", .{errors});2385 try std.testing.expectFmt("input.zon:1:3: error: expected type 'bool'\n", "{f}", .{errors.fmt("input.zon")});
2302 }2386 }
2303 }2387 }
23042388
...@@ -2315,7 +2399,10 @@ test "std.zon arrays and slices" {...@@ -2315,7 +2399,10 @@ test "std.zon arrays and slices" {
2315 .errors = &errors,2399 .errors = &errors,
2316 }),2400 }),
2317 );2401 );
2318 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{errors});2402 try std.testing.expectFmt(
2403 \\input.zon:1:1: error: expected array
2404 \\
2405 , "{f}", .{errors.fmt("input.zon")});
2319 }2406 }
23202407
2321 // Slice2408 // Slice
...@@ -2325,7 +2412,7 @@ test "std.zon arrays and slices" {...@@ -2325,7 +2412,7 @@ test "std.zon arrays and slices" {
2325 error.ParseZon,2412 error.ParseZon,
2326 fromSliceAlloc([]u8, .{ .gpa = gpa, .arena = arena, .source = "'a'", .errors = &errors }),2413 fromSliceAlloc([]u8, .{ .gpa = gpa, .arena = arena, .source = "'a'", .errors = &errors }),
2327 );2414 );
2328 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{errors});2415 try std.testing.expectFmt("input.zon:1:1: error: expected array\n", "{f}", .{errors.fmt("input.zon")});
2329 }2416 }
2330 }2417 }
23312418
...@@ -2337,10 +2424,9 @@ test "std.zon arrays and slices" {...@@ -2337,10 +2424,9 @@ test "std.zon arrays and slices" {
2337 fromSliceAlloc([]u8, .{ .gpa = gpa, .arena = arena, .source = " &.{'a', 'b', 'c'}", .errors = &errors }),2424 fromSliceAlloc([]u8, .{ .gpa = gpa, .arena = arena, .source = " &.{'a', 'b', 'c'}", .errors = &errors }),
2338 );2425 );
2339 try std.testing.expectFmt(2426 try std.testing.expectFmt(
2340 "1:3: error: pointers are not available in ZON\n",2427 \\input.zon:1:3: error: pointers are not available in ZON
2341 "{f}",2428 \\
2342 .{errors},2429 , "{f}", .{errors.fmt("input.zon")});
2343 );
2344 }2430 }
2345}2431}
23462432
...@@ -2391,7 +2477,7 @@ test "std.zon string literal" {...@@ -2391,7 +2477,7 @@ test "std.zon string literal" {
2391 error.ParseZon,2477 error.ParseZon,
2392 fromSliceAlloc([]u8, .{ .gpa = gpa, .arena = arena, .source = "\"abcd\"", .errors = &errors }),2478 fromSliceAlloc([]u8, .{ .gpa = gpa, .arena = arena, .source = "\"abcd\"", .errors = &errors }),
2393 );2479 );
2394 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{errors});2480 try std.testing.expectFmt("input.zon:1:1: error: expected array\n", "{f}", .{errors.fmt("input.zon")});
2395 }2481 }
23962482
2397 {2483 {
...@@ -2400,7 +2486,10 @@ test "std.zon string literal" {...@@ -2400,7 +2486,10 @@ test "std.zon string literal" {
2400 error.ParseZon,2486 error.ParseZon,
2401 fromSliceAlloc([]u8, .{ .gpa = gpa, .arena = arena, .source = "\\\\abcd", .errors = &errors }),2487 fromSliceAlloc([]u8, .{ .gpa = gpa, .arena = arena, .source = "\\\\abcd", .errors = &errors }),
2402 );2488 );
2403 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{errors});2489 try std.testing.expectFmt(
2490 \\input.zon:1:1: error: expected array
2491 \\
2492 , "{f}", .{errors.fmt("input.zon")});
2404 }2493 }
2405 }2494 }
24062495
...@@ -2420,7 +2509,7 @@ test "std.zon string literal" {...@@ -2420,7 +2509,7 @@ test "std.zon string literal" {
2420 .errors = &errors,2509 .errors = &errors,
2421 }),2510 }),
2422 );2511 );
2423 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{errors});2512 try std.testing.expectFmt("input.zon:1:1: error: expected array\n", "{f}", .{errors.fmt("input.zon")});
2424 }2513 }
24252514
2426 {2515 {
...@@ -2433,7 +2522,10 @@ test "std.zon string literal" {...@@ -2433,7 +2522,10 @@ test "std.zon string literal" {
2433 .errors = &errors,2522 .errors = &errors,
2434 }),2523 }),
2435 );2524 );
2436 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{errors});2525 try std.testing.expectFmt(
2526 \\input.zon:1:1: error: expected array
2527 \\
2528 , "{f}", .{errors.fmt("input.zon")});
2437 }2529 }
2438 }2530 }
24392531
...@@ -2470,7 +2562,7 @@ test "std.zon string literal" {...@@ -2470,7 +2562,7 @@ test "std.zon string literal" {
2470 error.ParseZon,2562 error.ParseZon,
2471 fromSliceAlloc([:1]const u8, .{ .gpa = gpa, .arena = arena, .source = "\"foo\"", .errors = &errors }),2563 fromSliceAlloc([:1]const u8, .{ .gpa = gpa, .arena = arena, .source = "\"foo\"", .errors = &errors }),
2472 );2564 );
2473 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{errors});2565 try std.testing.expectFmt("input.zon:1:1: error: expected array\n", "{f}", .{errors.fmt("input.zon")});
2474 }2566 }
24752567
2476 {2568 {
...@@ -2479,7 +2571,10 @@ test "std.zon string literal" {...@@ -2479,7 +2571,10 @@ test "std.zon string literal" {
2479 error.ParseZon,2571 error.ParseZon,
2480 fromSliceAlloc([:1]const u8, .{ .gpa = gpa, .arena = arena, .source = "\\\\foo", .errors = &errors }),2572 fromSliceAlloc([:1]const u8, .{ .gpa = gpa, .arena = arena, .source = "\\\\foo", .errors = &errors }),
2481 );2573 );
2482 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{errors});2574 try std.testing.expectFmt(
2575 \\input.zon:1:1: error: expected array
2576 \\
2577 , "{f}", .{errors.fmt("input.zon")});
2483 }2578 }
2484 }2579 }
24852580
...@@ -2490,7 +2585,10 @@ test "std.zon string literal" {...@@ -2490,7 +2585,10 @@ test "std.zon string literal" {
2490 error.ParseZon,2585 error.ParseZon,
2491 fromSliceAlloc([]const u8, .{ .gpa = gpa, .arena = arena, .source = "true", .errors = &errors }),2586 fromSliceAlloc([]const u8, .{ .gpa = gpa, .arena = arena, .source = "true", .errors = &errors }),
2492 );2587 );
2493 try std.testing.expectFmt("1:1: error: expected string\n", "{f}", .{errors});2588 try std.testing.expectFmt(
2589 \\input.zon:1:1: error: expected string
2590 \\
2591 , "{f}", .{errors.fmt("input.zon")});
2494 }2592 }
24952593
2496 // Expecting string literal, getting an incompatible tuple2594 // Expecting string literal, getting an incompatible tuple
...@@ -2500,7 +2598,10 @@ test "std.zon string literal" {...@@ -2500,7 +2598,10 @@ test "std.zon string literal" {
2500 error.ParseZon,2598 error.ParseZon,
2501 fromSliceAlloc([]const u8, .{ .gpa = gpa, .arena = arena, .source = ".{false}", .errors = &errors }),2599 fromSliceAlloc([]const u8, .{ .gpa = gpa, .arena = arena, .source = ".{false}", .errors = &errors }),
2502 );2600 );
2503 try std.testing.expectFmt("1:3: error: expected type 'u8'\n", "{f}", .{errors});2601 try std.testing.expectFmt(
2602 \\input.zon:1:3: error: expected type 'u8'
2603 \\
2604 , "{f}", .{errors.fmt("input.zon")});
2504 }2605 }
25052606
2506 // Invalid string literal2607 // Invalid string literal
...@@ -2510,7 +2611,10 @@ test "std.zon string literal" {...@@ -2510,7 +2611,10 @@ test "std.zon string literal" {
2510 error.ParseZon,2611 error.ParseZon,
2511 fromSliceAlloc([]const i8, .{ .gpa = gpa, .arena = arena, .source = "\"\\a\"", .errors = &errors }),2612 fromSliceAlloc([]const i8, .{ .gpa = gpa, .arena = arena, .source = "\"\\a\"", .errors = &errors }),
2512 );2613 );
2513 try std.testing.expectFmt("1:3: error: invalid escape character: 'a'\n", "{f}", .{errors});2614 try std.testing.expectFmt(
2615 \\input.zon:1:3: error: invalid escape character: 'a'
2616 \\
2617 , "{f}", .{errors.fmt("input.zon")});
2514 }2618 }
25152619
2516 // Slice wrong child type2620 // Slice wrong child type
...@@ -2521,7 +2625,10 @@ test "std.zon string literal" {...@@ -2521,7 +2625,10 @@ test "std.zon string literal" {
2521 error.ParseZon,2625 error.ParseZon,
2522 fromSliceAlloc([]const i8, .{ .gpa = gpa, .arena = arena, .source = "\"a\"", .errors = &errors }),2626 fromSliceAlloc([]const i8, .{ .gpa = gpa, .arena = arena, .source = "\"a\"", .errors = &errors }),
2523 );2627 );
2524 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{errors});2628 try std.testing.expectFmt(
2629 \\input.zon:1:1: error: expected array
2630 \\
2631 , "{f}", .{errors.fmt("input.zon")});
2525 }2632 }
25262633
2527 {2634 {
...@@ -2530,7 +2637,10 @@ test "std.zon string literal" {...@@ -2530,7 +2637,10 @@ test "std.zon string literal" {
2530 error.ParseZon,2637 error.ParseZon,
2531 fromSliceAlloc([]const i8, .{ .gpa = gpa, .arena = arena, .source = "\\\\a", .errors = &errors }),2638 fromSliceAlloc([]const i8, .{ .gpa = gpa, .arena = arena, .source = "\\\\a", .errors = &errors }),
2532 );2639 );
2533 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{errors});2640 try std.testing.expectFmt(
2641 \\input.zon:1:1: error: expected array
2642 \\
2643 , "{f}", .{errors.fmt("input.zon")});
2534 }2644 }
2535 }2645 }
25362646
...@@ -2547,7 +2657,7 @@ test "std.zon string literal" {...@@ -2547,7 +2657,7 @@ test "std.zon string literal" {
2547 .errors = &errors,2657 .errors = &errors,
2548 }),2658 }),
2549 );2659 );
2550 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{errors});2660 try std.testing.expectFmt("input.zon:1:1: error: expected array\n", "{f}", .{errors.fmt("input.zon")});
2551 }2661 }
25522662
2553 {2663 {
...@@ -2561,7 +2671,10 @@ test "std.zon string literal" {...@@ -2561,7 +2671,10 @@ test "std.zon string literal" {
2561 .errors = &errors,2671 .errors = &errors,
2562 }),2672 }),
2563 );2673 );
2564 try std.testing.expectFmt("1:1: error: expected array\n", "{f}", .{errors});2674 try std.testing.expectFmt(
2675 \\input.zon:1:1: error: expected array
2676 \\
2677 , "{f}", .{errors.fmt("input.zon")});
2565 }2678 }
2566 }2679 }
25672680
...@@ -2657,13 +2770,10 @@ test "std.zon enum literals" {...@@ -2657,13 +2770,10 @@ test "std.zon enum literals" {
2657 }),2770 }),
2658 );2771 );
2659 try std.testing.expectFmt(2772 try std.testing.expectFmt(
2660 \\1:2: error: unexpected enum literal 'qux'2773 \\input.zon:1:2: error: unexpected enum literal 'qux'
2661 \\1:2: note: supported: 'foo', 'bar', 'baz', '@"ab\nc"'2774 \\input.zon:1:2: note: supported: 'foo', 'bar', 'baz', '@"ab\nc"'
2662 \\2775 \\
2663 ,2776 , "{f}", .{errors.fmt("input.zon")});
2664 "{f}",
2665 .{errors},
2666 );
2667 }2777 }
26682778
2669 // Bad tag that's too long for parser2779 // Bad tag that's too long for parser
...@@ -2678,13 +2788,10 @@ test "std.zon enum literals" {...@@ -2678,13 +2788,10 @@ test "std.zon enum literals" {
2678 }),2788 }),
2679 );2789 );
2680 try std.testing.expectFmt(2790 try std.testing.expectFmt(
2681 \\1:2: error: unexpected enum literal 'foobarbaz'2791 \\input.zon:1:2: error: unexpected enum literal 'foobarbaz'
2682 \\1:2: note: supported: 'foo', 'bar', 'baz', '@"ab\nc"'2792 \\input.zon:1:2: note: supported: 'foo', 'bar', 'baz', '@"ab\nc"'
2683 \\2793 \\
2684 ,2794 , "{f}", .{errors.fmt("input.zon")});
2685 "{f}",
2686 .{errors},
2687 );
2688 }2795 }
26892796
2690 // Bad type2797 // Bad type
...@@ -2698,7 +2805,10 @@ test "std.zon enum literals" {...@@ -2698,7 +2805,10 @@ test "std.zon enum literals" {
2698 .errors = &errors,2805 .errors = &errors,
2699 }),2806 }),
2700 );2807 );
2701 try std.testing.expectFmt("1:1: error: expected enum literal\n", "{f}", .{errors});2808 try std.testing.expectFmt(
2809 \\input.zon:1:1: error: expected enum literal
2810 \\
2811 , "{f}", .{errors.fmt("input.zon")});
2702 }2812 }
27032813
2704 // Test embedded nulls in an identifier2814 // Test embedded nulls in an identifier
...@@ -2713,10 +2823,9 @@ test "std.zon enum literals" {...@@ -2713,10 +2823,9 @@ test "std.zon enum literals" {
2713 }),2823 }),
2714 );2824 );
2715 try std.testing.expectFmt(2825 try std.testing.expectFmt(
2716 "1:2: error: identifier cannot contain null bytes\n",2826 \\input.zon:1:2: error: identifier cannot contain null bytes
2717 "{f}",2827 \\
2718 .{errors},2828 , "{f}", .{errors.fmt("input.zon")});
2719 );
2720 }2829 }
2721}2830}
27222831
...@@ -2750,11 +2859,11 @@ test "std.zon parse bool" {...@@ -2750,11 +2859,11 @@ test "std.zon parse bool" {
2750 }),2859 }),
2751 );2860 );
2752 try std.testing.expectFmt(2861 try std.testing.expectFmt(
2753 \\1:2: error: invalid expression2862 \\input.zon:1:2: error: invalid expression
2754 \\1:2: note: ZON allows identifiers 'true', 'false', 'null', 'inf', and 'nan'2863 \\input.zon:1:2: note: ZON allows identifiers 'true', 'false', 'null', 'inf', and 'nan'
2755 \\1:2: note: precede identifier with '.' for an enum literal2864 \\input.zon:1:2: note: precede identifier with '.' for an enum literal
2756 \\2865 \\
2757 , "{f}", .{errors});2866 , "{f}", .{errors.fmt("input.zon")});
2758 }2867 }
2759 {2868 {
2760 var errors: Errors = .init(arena);2869 var errors: Errors = .init(arena);
...@@ -2763,7 +2872,10 @@ test "std.zon parse bool" {...@@ -2763,7 +2872,10 @@ test "std.zon parse bool" {
2763 .source = "123",2872 .source = "123",
2764 .errors = &errors,2873 .errors = &errors,
2765 }));2874 }));
2766 try std.testing.expectFmt("1:1: error: expected type 'bool'\n", "{f}", .{errors});2875 try std.testing.expectFmt(
2876 \\input.zon:1:1: error: expected type 'bool'
2877 \\
2878 , "{f}", .{errors.fmt("input.zon")});
2767 }2879 }
2768}2880}
27692881
...@@ -2892,10 +3004,9 @@ test "std.zon parse int" {...@@ -2892,10 +3004,9 @@ test "std.zon parse int" {
2892 .errors = &errors,3004 .errors = &errors,
2893 }));3005 }));
2894 try std.testing.expectFmt(3006 try std.testing.expectFmt(
2895 "1:1: error: type 'i66' cannot represent value\n",3007 \\input.zon:1:1: error: type 'i66' cannot represent value
2896 "{f}",3008 \\
2897 .{errors},3009 , "{f}", .{errors.fmt("input.zon")});
2898 );
2899 }3010 }
2900 {3011 {
2901 var errors: Errors = .init(arena);3012 var errors: Errors = .init(arena);
...@@ -2905,10 +3016,9 @@ test "std.zon parse int" {...@@ -2905,10 +3016,9 @@ test "std.zon parse int" {
2905 .errors = &errors,3016 .errors = &errors,
2906 }));3017 }));
2907 try std.testing.expectFmt(3018 try std.testing.expectFmt(
2908 "1:1: error: type 'i66' cannot represent value\n",3019 \\input.zon:1:1: error: type 'i66' cannot represent value
2909 "{f}",3020 \\
2910 .{errors},3021 , "{f}", .{errors.fmt("input.zon")});
2911 );
2912 }3022 }
29133023
2914 // Test parsing whole number floats as integers3024 // Test parsing whole number floats as integers
...@@ -3011,10 +3121,9 @@ test "std.zon parse int" {...@@ -3011,10 +3121,9 @@ test "std.zon parse int" {
3011 .errors = &errors,3121 .errors = &errors,
3012 }));3122 }));
3013 try std.testing.expectFmt(3123 try std.testing.expectFmt(
3014 "1:3: error: invalid digit 'a' for decimal base\n",3124 \\input.zon:1:3: error: invalid digit 'a' for decimal base
3015 "{f}",3125 \\
3016 .{errors},3126 , "{f}", .{errors.fmt("input.zon")});
3017 );
3018 }3127 }
30193128
3020 // Failing to parse as int3129 // Failing to parse as int
...@@ -3025,7 +3134,10 @@ test "std.zon parse int" {...@@ -3025,7 +3134,10 @@ test "std.zon parse int" {
3025 .source = "true",3134 .source = "true",
3026 .errors = &errors,3135 .errors = &errors,
3027 }));3136 }));
3028 try std.testing.expectFmt("1:1: error: expected type 'u8'\n", "{f}", .{errors});3137 try std.testing.expectFmt(
3138 \\input.zon:1:1: error: expected type 'u8'
3139 \\
3140 , "{f}", .{errors.fmt("input.zon")});
3029 }3141 }
30303142
3031 // Failing because an int is out of range3143 // Failing because an int is out of range
...@@ -3037,10 +3149,9 @@ test "std.zon parse int" {...@@ -3037,10 +3149,9 @@ test "std.zon parse int" {
3037 .errors = &errors,3149 .errors = &errors,
3038 }));3150 }));
3039 try std.testing.expectFmt(3151 try std.testing.expectFmt(
3040 "1:1: error: type 'u8' cannot represent value\n",3152 \\input.zon:1:1: error: type 'u8' cannot represent value
3041 "{f}",3153 \\
3042 .{errors},3154 , "{f}", .{errors.fmt("input.zon")});
3043 );
3044 }3155 }
30453156
3046 // Failing because a negative int is out of range3157 // Failing because a negative int is out of range
...@@ -3052,10 +3163,9 @@ test "std.zon parse int" {...@@ -3052,10 +3163,9 @@ test "std.zon parse int" {
3052 .errors = &errors,3163 .errors = &errors,
3053 }));3164 }));
3054 try std.testing.expectFmt(3165 try std.testing.expectFmt(
3055 "1:1: error: type 'i8' cannot represent value\n",3166 \\input.zon:1:1: error: type 'i8' cannot represent value
3056 "{f}",3167 \\
3057 .{errors},3168 , "{f}", .{errors.fmt("input.zon")});
3058 );
3059 }3169 }
30603170
3061 // Failing because an unsigned int is negative3171 // Failing because an unsigned int is negative
...@@ -3067,10 +3177,9 @@ test "std.zon parse int" {...@@ -3067,10 +3177,9 @@ test "std.zon parse int" {
3067 .errors = &errors,3177 .errors = &errors,
3068 }));3178 }));
3069 try std.testing.expectFmt(3179 try std.testing.expectFmt(
3070 "1:1: error: type 'u8' cannot represent value\n",3180 \\input.zon:1:1: error: type 'u8' cannot represent value
3071 "{f}",3181 \\
3072 .{errors},3182 , "{f}", .{errors.fmt("input.zon")});
3073 );
3074 }3183 }
30753184
3076 // Failing because a float is non-whole3185 // Failing because a float is non-whole
...@@ -3082,10 +3191,9 @@ test "std.zon parse int" {...@@ -3082,10 +3191,9 @@ test "std.zon parse int" {
3082 .errors = &errors,3191 .errors = &errors,
3083 }));3192 }));
3084 try std.testing.expectFmt(3193 try std.testing.expectFmt(
3085 "1:1: error: type 'u8' cannot represent value\n",3194 \\input.zon:1:1: error: type 'u8' cannot represent value
3086 "{f}",3195 \\
3087 .{errors},3196 , "{f}", .{errors.fmt("input.zon")});
3088 );
3089 }3197 }
30903198
3091 // Failing because a float is negative3199 // Failing because a float is negative
...@@ -3097,10 +3205,9 @@ test "std.zon parse int" {...@@ -3097,10 +3205,9 @@ test "std.zon parse int" {
3097 .errors = &errors,3205 .errors = &errors,
3098 }));3206 }));
3099 try std.testing.expectFmt(3207 try std.testing.expectFmt(
3100 "1:1: error: type 'u8' cannot represent value\n",3208 \\input.zon:1:1: error: type 'u8' cannot represent value
3101 "{f}",3209 \\
3102 .{errors},3210 , "{f}", .{errors.fmt("input.zon")});
3103 );
3104 }3211 }
31053212
3106 // Negative integer zero3213 // Negative integer zero
...@@ -3112,11 +3219,11 @@ test "std.zon parse int" {...@@ -3112,11 +3219,11 @@ test "std.zon parse int" {
3112 .errors = &errors,3219 .errors = &errors,
3113 }));3220 }));
3114 try std.testing.expectFmt(3221 try std.testing.expectFmt(
3115 \\1:2: error: integer literal '-0' is ambiguous3222 \\input.zon:1:2: error: integer literal '-0' is ambiguous
3116 \\1:2: note: use '0' for an integer zero3223 \\input.zon:1:2: note: use '0' for an integer zero
3117 \\1:2: note: use '-0.0' for a floating-point signed zero3224 \\input.zon:1:2: note: use '-0.0' for a floating-point signed zero
3118 \\3225 \\
3119 , "{f}", .{errors});3226 , "{f}", .{errors.fmt("input.zon")});
3120 }3227 }
31213228
3122 // Negative integer zero casted to float3229 // Negative integer zero casted to float
...@@ -3128,11 +3235,11 @@ test "std.zon parse int" {...@@ -3128,11 +3235,11 @@ test "std.zon parse int" {
3128 .errors = &errors,3235 .errors = &errors,
3129 }));3236 }));
3130 try std.testing.expectFmt(3237 try std.testing.expectFmt(
3131 \\1:2: error: integer literal '-0' is ambiguous3238 \\input.zon:1:2: error: integer literal '-0' is ambiguous
3132 \\1:2: note: use '0' for an integer zero3239 \\input.zon:1:2: note: use '0' for an integer zero
3133 \\1:2: note: use '-0.0' for a floating-point signed zero3240 \\input.zon:1:2: note: use '-0.0' for a floating-point signed zero
3134 \\3241 \\
3135 , "{f}", .{errors});3242 , "{f}", .{errors.fmt("input.zon")});
3136 }3243 }
31373244
3138 // Negative float 0 is allowed3245 // Negative float 0 is allowed
...@@ -3157,11 +3264,7 @@ test "std.zon parse int" {...@@ -3157,11 +3264,7 @@ test "std.zon parse int" {
3157 .source = "--2",3264 .source = "--2",
3158 .errors = &errors,3265 .errors = &errors,
3159 }));3266 }));
3160 try std.testing.expectFmt(3267 try std.testing.expectFmt("input.zon:1:1: error: expected number or 'inf' after '-'\n", "{f}", .{errors.fmt("input.zon")});
3161 "1:1: error: expected number or 'inf' after '-'\n",
3162 "{f}",
3163 .{errors},
3164 );
3165 }3268 }
31663269
3167 {3270 {
...@@ -3175,10 +3278,9 @@ test "std.zon parse int" {...@@ -3175,10 +3278,9 @@ test "std.zon parse int" {
3175 }),3278 }),
3176 );3279 );
3177 try std.testing.expectFmt(3280 try std.testing.expectFmt(
3178 "1:1: error: expected number or 'inf' after '-'\n",3281 \\input.zon:1:1: error: expected number or 'inf' after '-'
3179 "{f}",3282 \\
3180 .{errors},3283 , "{f}", .{errors.fmt("input.zon")});
3181 );
3182 }3284 }
31833285
3184 // Invalid int literal3286 // Invalid int literal
...@@ -3189,7 +3291,10 @@ test "std.zon parse int" {...@@ -3189,7 +3291,10 @@ test "std.zon parse int" {
3189 .source = "0xg",3291 .source = "0xg",
3190 .errors = &errors,3292 .errors = &errors,
3191 }));3293 }));
3192 try std.testing.expectFmt("1:3: error: invalid digit 'g' for hex base\n", "{f}", .{errors});3294 try std.testing.expectFmt(
3295 \\input.zon:1:3: error: invalid digit 'g' for hex base
3296 \\
3297 , "{f}", .{errors.fmt("input.zon")});
3193 }3298 }
31943299
3195 // Notes on invalid int literal3300 // Notes on invalid int literal
...@@ -3201,10 +3306,10 @@ test "std.zon parse int" {...@@ -3201,10 +3306,10 @@ test "std.zon parse int" {
3201 .errors = &errors,3306 .errors = &errors,
3202 }));3307 }));
3203 try std.testing.expectFmt(3308 try std.testing.expectFmt(
3204 \\1:1: error: number '0123' has leading zero3309 \\input.zon:1:1: error: number '0123' has leading zero
3205 \\1:1: note: use '0o' prefix for octal literals3310 \\input.zon:1:1: note: use '0o' prefix for octal literals
3206 \\3311 \\
3207 , "{f}", .{errors});3312 , "{f}", .{errors.fmt("input.zon")});
3208 }3313 }
3209}3314}
32103315
...@@ -3222,10 +3327,9 @@ test "std.zon negative char" {...@@ -3222,10 +3327,9 @@ test "std.zon negative char" {
3222 .errors = &errors,3327 .errors = &errors,
3223 }));3328 }));
3224 try std.testing.expectFmt(3329 try std.testing.expectFmt(
3225 "1:1: error: expected number or 'inf' after '-'\n",3330 \\input.zon:1:1: error: expected number or 'inf' after '-'
3226 "{f}",3331 \\
3227 .{errors},3332 , "{f}", .{errors.fmt("input.zon")});
3228 );
3229 }3333 }
3230 {3334 {
3231 var errors: Errors = .init(arena);3335 var errors: Errors = .init(arena);
...@@ -3235,14 +3339,15 @@ test "std.zon negative char" {...@@ -3235,14 +3339,15 @@ test "std.zon negative char" {
3235 .errors = &errors,3339 .errors = &errors,
3236 }));3340 }));
3237 try std.testing.expectFmt(3341 try std.testing.expectFmt(
3238 "1:1: error: expected number or 'inf' after '-'\n",3342 \\input.zon:1:1: error: expected number or 'inf' after '-'
3239 "{f}",3343 \\
3240 .{errors},3344 , "{f}", .{errors.fmt("input.zon")});
3241 );
3242 }3345 }
3243}3346}
32443347
3245test "std.zon parse float" {3348test "std.zon parse float" {
3349 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
3350
3246 const gpa = std.testing.allocator;3351 const gpa = std.testing.allocator;
3247 var arena_allocator: ArenaAllocator = .init(gpa);3352 var arena_allocator: ArenaAllocator = .init(gpa);
3248 defer arena_allocator.deinit();3353 defer arena_allocator.deinit();
...@@ -3399,11 +3504,7 @@ test "std.zon parse float" {...@@ -3399,11 +3504,7 @@ test "std.zon parse float" {
3399 .source = "-nan",3504 .source = "-nan",
3400 .errors = &errors,3505 .errors = &errors,
3401 }));3506 }));
3402 try std.testing.expectFmt(3507 try std.testing.expectFmt("input.zon:1:1: error: expected number or 'inf' after '-'\n", "{f}", .{errors.fmt("input.zon")});
3403 "1:1: error: expected number or 'inf' after '-'\n",
3404 "{f}",
3405 .{errors},
3406 );
3407 }3508 }
34083509
3409 // nan as int not allowed3510 // nan as int not allowed
...@@ -3414,7 +3515,10 @@ test "std.zon parse float" {...@@ -3414,7 +3515,10 @@ test "std.zon parse float" {
3414 .source = "nan",3515 .source = "nan",
3415 .errors = &errors,3516 .errors = &errors,
3416 }));3517 }));
3417 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{f}", .{errors});3518 try std.testing.expectFmt(
3519 \\input.zon:1:1: error: expected type 'i8'
3520 \\
3521 , "{f}", .{errors.fmt("input.zon")});
3418 }3522 }
34193523
3420 // nan as int not allowed3524 // nan as int not allowed
...@@ -3425,7 +3529,10 @@ test "std.zon parse float" {...@@ -3425,7 +3529,10 @@ test "std.zon parse float" {
3425 .source = "nan",3529 .source = "nan",
3426 .errors = &errors,3530 .errors = &errors,
3427 }));3531 }));
3428 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{f}", .{errors});3532 try std.testing.expectFmt(
3533 \\input.zon:1:1: error: expected type 'i8'
3534 \\
3535 , "{f}", .{errors.fmt("input.zon")});
3429 }3536 }
34303537
3431 // inf as int not allowed3538 // inf as int not allowed
...@@ -3436,7 +3543,10 @@ test "std.zon parse float" {...@@ -3436,7 +3543,10 @@ test "std.zon parse float" {
3436 .source = "inf",3543 .source = "inf",
3437 .errors = &errors,3544 .errors = &errors,
3438 }));3545 }));
3439 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{f}", .{errors});3546 try std.testing.expectFmt(
3547 \\input.zon:1:1: error: expected type 'i8'
3548 \\
3549 , "{f}", .{errors.fmt("input.zon")});
3440 }3550 }
34413551
3442 // -inf as int not allowed3552 // -inf as int not allowed
...@@ -3447,7 +3557,10 @@ test "std.zon parse float" {...@@ -3447,7 +3557,10 @@ test "std.zon parse float" {
3447 .source = "-inf",3557 .source = "-inf",
3448 .errors = &errors,3558 .errors = &errors,
3449 }));3559 }));
3450 try std.testing.expectFmt("1:1: error: expected type 'i8'\n", "{f}", .{errors});3560 try std.testing.expectFmt(
3561 \\input.zon:1:1: error: expected type 'i8'
3562 \\
3563 , "{f}", .{errors.fmt("input.zon")});
3451 }3564 }
34523565
3453 // Bad identifier as float3566 // Bad identifier as float
...@@ -3459,11 +3572,11 @@ test "std.zon parse float" {...@@ -3459,11 +3572,11 @@ test "std.zon parse float" {
3459 .errors = &errors,3572 .errors = &errors,
3460 }));3573 }));
3461 try std.testing.expectFmt(3574 try std.testing.expectFmt(
3462 \\1:1: error: invalid expression3575 \\input.zon:1:1: error: invalid expression
3463 \\1:1: note: ZON allows identifiers 'true', 'false', 'null', 'inf', and 'nan'3576 \\input.zon:1:1: note: ZON allows identifiers 'true', 'false', 'null', 'inf', and 'nan'
3464 \\1:1: note: precede identifier with '.' for an enum literal3577 \\input.zon:1:1: note: precede identifier with '.' for an enum literal
3465 \\3578 \\
3466 , "{f}", .{errors});3579 , "{f}", .{errors.fmt("input.zon")});
3467 }3580 }
34683581
3469 {3582 {
...@@ -3474,10 +3587,9 @@ test "std.zon parse float" {...@@ -3474,10 +3587,9 @@ test "std.zon parse float" {
3474 .errors = &errors,3587 .errors = &errors,
3475 }));3588 }));
3476 try std.testing.expectFmt(3589 try std.testing.expectFmt(
3477 "1:1: error: expected number or 'inf' after '-'\n",3590 \\input.zon:1:1: error: expected number or 'inf' after '-'
3478 "{f}",3591 \\
3479 .{errors},3592 , "{f}", .{errors.fmt("input.zon")});
3480 );
3481 }3593 }
34823594
3483 // Non float as float3595 // Non float as float
...@@ -3491,7 +3603,10 @@ test "std.zon parse float" {...@@ -3491,7 +3603,10 @@ test "std.zon parse float" {
3491 .errors = &errors,3603 .errors = &errors,
3492 }),3604 }),
3493 );3605 );
3494 try std.testing.expectFmt("1:1: error: expected type 'f32'\n", "{f}", .{errors});3606 try std.testing.expectFmt(
3607 \\input.zon:1:1: error: expected type 'f32'
3608 \\
3609 , "{f}", .{errors.fmt("input.zon")});
3495 }3610 }
3496}3611}
34973612
...@@ -3612,7 +3727,7 @@ test "std.zon free on error" {...@@ -3612,7 +3727,7 @@ test "std.zon free on error" {
3612}3727}
36133728
3614test "std.zon vector" {3729test "std.zon vector" {
3615 const builtin = @import("builtin");3730 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/15330
3616 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .s390x) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/259573731 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .s390x) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/25957
36173732
3618 const gpa = std.testing.allocator;3733 const gpa = std.testing.allocator;
...@@ -3722,10 +3837,9 @@ test "std.zon vector" {...@@ -3722,10 +3837,9 @@ test "std.zon vector" {
3722 }),3837 }),
3723 );3838 );
3724 try std.testing.expectFmt(3839 try std.testing.expectFmt(
3725 "1:2: error: expected 2 array elements; found 1\n",3840 \\input.zon:1:2: error: expected 2 array elements; found 1
3726 "{f}",3841 \\
3727 .{errors},3842 , "{f}", .{errors.fmt("input.zon")});
3728 );
3729 }3843 }
37303844
3731 // Too many fields3845 // Too many fields
...@@ -3740,10 +3854,9 @@ test "std.zon vector" {...@@ -3740,10 +3854,9 @@ test "std.zon vector" {
3740 }),3854 }),
3741 );3855 );
3742 try std.testing.expectFmt(3856 try std.testing.expectFmt(
3743 "1:13: error: index 2 outside of array of length 2\n",3857 \\input.zon:1:13: error: index 2 outside of array of length 2
3744 "{f}",3858 \\
3745 .{errors},3859 , "{f}", .{errors.fmt("input.zon")});
3746 );
3747 }3860 }
37483861
3749 // Wrong type fields3862 // Wrong type fields
...@@ -3758,10 +3871,9 @@ test "std.zon vector" {...@@ -3758,10 +3871,9 @@ test "std.zon vector" {
3758 }),3871 }),
3759 );3872 );
3760 try std.testing.expectFmt(3873 try std.testing.expectFmt(
3761 "1:8: error: expected type 'f32'\n",3874 \\input.zon:1:8: error: expected type 'f32'
3762 "{f}",3875 \\
3763 .{errors},3876 , "{f}", .{errors.fmt("input.zon")});
3764 );
3765 }3877 }
37663878
3767 // Wrong type3879 // Wrong type
...@@ -3775,7 +3887,10 @@ test "std.zon vector" {...@@ -3775,7 +3887,10 @@ test "std.zon vector" {
3775 .errors = &errors,3887 .errors = &errors,
3776 }),3888 }),
3777 );3889 );
3778 try std.testing.expectFmt("1:1: error: expected type '@Vector(3, u8)'\n", "{f}", .{errors});3890 try std.testing.expectFmt(
3891 \\input.zon:1:1: error: expected type '@Vector(3, u8)'
3892 \\
3893 , "{f}", .{errors.fmt("input.zon")});
3779 }3894 }
37803895
3781 // Elements should get freed on error3896 // Elements should get freed on error
...@@ -3790,7 +3905,10 @@ test "std.zon vector" {...@@ -3790,7 +3905,10 @@ test "std.zon vector" {
3790 .errors = &errors,3905 .errors = &errors,
3791 }),3906 }),
3792 );3907 );
3793 try std.testing.expectFmt("1:6: error: expected type 'u8'\n", "{f}", .{errors});3908 try std.testing.expectFmt(
3909 \\input.zon:1:6: error: expected type 'u8'
3910 \\
3911 , "{f}", .{errors.fmt("input.zon")});
3794 }3912 }
3795}3913}
37963914
...@@ -3981,7 +4099,10 @@ test "std.zon add pointers" {...@@ -3981,7 +4099,10 @@ test "std.zon add pointers" {
3981 .errors = &errors,4099 .errors = &errors,
3982 }),4100 }),
3983 );4101 );
3984 try std.testing.expectFmt("1:1: error: expected type '?u8'\n", "{f}", .{errors});4102 try std.testing.expectFmt(
4103 \\input.zon:1:1: error: expected type '?u8'
4104 \\
4105 , "{f}", .{errors.fmt("input.zon")});
3985 }4106 }
39864107
3987 {4108 {
...@@ -3995,7 +4116,10 @@ test "std.zon add pointers" {...@@ -3995,7 +4116,10 @@ test "std.zon add pointers" {
3995 .errors = &errors,4116 .errors = &errors,
3996 }),4117 }),
3997 );4118 );
3998 try std.testing.expectFmt("1:1: error: expected type '?f32'\n", "{f}", .{errors});4119 try std.testing.expectFmt(
4120 \\input.zon:1:1: error: expected type '?f32'
4121 \\
4122 , "{f}", .{errors.fmt("input.zon")});
3999 }4123 }
40004124
4001 {4125 {
...@@ -4009,7 +4133,10 @@ test "std.zon add pointers" {...@@ -4009,7 +4133,10 @@ test "std.zon add pointers" {
4009 .errors = &errors,4133 .errors = &errors,
4010 }),4134 }),
4011 );4135 );
4012 try std.testing.expectFmt("1:1: error: expected type '?@Vector(3, u8)'\n", "{f}", .{errors});4136 try std.testing.expectFmt(
4137 \\input.zon:1:1: error: expected type '?@Vector(3, u8)'
4138 \\
4139 , "{f}", .{errors.fmt("input.zon")});
4013 }4140 }
40144141
4015 {4142 {
...@@ -4023,7 +4150,10 @@ test "std.zon add pointers" {...@@ -4023,7 +4150,10 @@ test "std.zon add pointers" {
4023 .errors = &errors,4150 .errors = &errors,
4024 }),4151 }),
4025 );4152 );
4026 try std.testing.expectFmt("1:1: error: expected type '?bool'\n", "{f}", .{errors});4153 try std.testing.expectFmt(
4154 \\input.zon:1:1: error: expected type '?bool'
4155 \\
4156 , "{f}", .{errors.fmt("input.zon")});
4027 }4157 }
40284158
4029 {4159 {
...@@ -4037,7 +4167,10 @@ test "std.zon add pointers" {...@@ -4037,7 +4167,10 @@ test "std.zon add pointers" {
4037 .errors = &errors,4167 .errors = &errors,
4038 }),4168 }),
4039 );4169 );
4040 try std.testing.expectFmt("1:1: error: expected optional struct\n", "{f}", .{errors});4170 try std.testing.expectFmt(
4171 \\input.zon:1:1: error: expected optional struct
4172 \\
4173 , "{f}", .{errors.fmt("input.zon")});
4041 }4174 }
40424175
4043 {4176 {
...@@ -4051,7 +4184,10 @@ test "std.zon add pointers" {...@@ -4051,7 +4184,10 @@ test "std.zon add pointers" {
4051 .errors = &errors,4184 .errors = &errors,
4052 }),4185 }),
4053 );4186 );
4054 try std.testing.expectFmt("1:1: error: expected optional tuple\n", "{f}", .{errors});4187 try std.testing.expectFmt(
4188 \\input.zon:1:1: error: expected optional tuple
4189 \\
4190 , "{f}", .{errors.fmt("input.zon")});
4055 }4191 }
40564192
4057 {4193 {
...@@ -4065,7 +4201,10 @@ test "std.zon add pointers" {...@@ -4065,7 +4201,10 @@ test "std.zon add pointers" {
4065 .errors = &errors,4201 .errors = &errors,
4066 }),4202 }),
4067 );4203 );
4068 try std.testing.expectFmt("1:1: error: expected optional union\n", "{f}", .{errors});4204 try std.testing.expectFmt(
4205 \\input.zon:1:1: error: expected optional union
4206 \\
4207 , "{f}", .{errors.fmt("input.zon")});
4069 }4208 }
40704209
4071 {4210 {
...@@ -4079,7 +4218,10 @@ test "std.zon add pointers" {...@@ -4079,7 +4218,10 @@ test "std.zon add pointers" {
4079 .errors = &errors,4218 .errors = &errors,
4080 }),4219 }),
4081 );4220 );
4082 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{errors});4221 try std.testing.expectFmt(
4222 \\input.zon:1:1: error: expected optional array
4223 \\
4224 , "{f}", .{errors.fmt("input.zon")});
4083 }4225 }
40844226
4085 {4227 {
...@@ -4093,7 +4235,10 @@ test "std.zon add pointers" {...@@ -4093,7 +4235,10 @@ test "std.zon add pointers" {
4093 .errors = &errors,4235 .errors = &errors,
4094 }),4236 }),
4095 );4237 );
4096 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{errors});4238 try std.testing.expectFmt(
4239 \\input.zon:1:1: error: expected optional array
4240 \\
4241 , "{f}", .{errors.fmt("input.zon")});
4097 }4242 }
40984243
4099 {4244 {
...@@ -4107,7 +4252,10 @@ test "std.zon add pointers" {...@@ -4107,7 +4252,10 @@ test "std.zon add pointers" {
4107 .errors = &errors,4252 .errors = &errors,
4108 }),4253 }),
4109 );4254 );
4110 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{errors});4255 try std.testing.expectFmt(
4256 \\input.zon:1:1: error: expected optional array
4257 \\
4258 , "{f}", .{errors.fmt("input.zon")});
4111 }4259 }
41124260
4113 {4261 {
...@@ -4121,7 +4269,10 @@ test "std.zon add pointers" {...@@ -4121,7 +4269,10 @@ test "std.zon add pointers" {
4121 .errors = &errors,4269 .errors = &errors,
4122 }),4270 }),
4123 );4271 );
4124 try std.testing.expectFmt("1:1: error: expected optional array\n", "{f}", .{errors});4272 try std.testing.expectFmt(
4273 \\input.zon:1:1: error: expected optional array
4274 \\
4275 , "{f}", .{errors.fmt("input.zon")});
4125 }4276 }
41264277
4127 {4278 {
...@@ -4135,7 +4286,10 @@ test "std.zon add pointers" {...@@ -4135,7 +4286,10 @@ test "std.zon add pointers" {
4135 .errors = &errors,4286 .errors = &errors,
4136 }),4287 }),
4137 );4288 );
4138 try std.testing.expectFmt("1:1: error: expected optional string\n", "{f}", .{errors});4289 try std.testing.expectFmt(
4290 \\input.zon:1:1: error: expected optional string
4291 \\
4292 , "{f}", .{errors.fmt("input.zon")});
4139 }4293 }
41404294
4141 {4295 {
...@@ -4149,7 +4303,10 @@ test "std.zon add pointers" {...@@ -4149,7 +4303,10 @@ test "std.zon add pointers" {
4149 .errors = &errors,4303 .errors = &errors,
4150 }),4304 }),
4151 );4305 );
4152 try std.testing.expectFmt("1:1: error: expected optional enum literal\n", "{f}", .{errors});4306 try std.testing.expectFmt(
4307 \\input.zon:1:1: error: expected optional enum literal
4308 \\
4309 , "{f}", .{errors.fmt("input.zon")});
4153 }4310 }
4154}4311}
41554312
...@@ -4437,7 +4594,10 @@ test "std.zon update optionals" {...@@ -4437,7 +4594,10 @@ test "std.zon update optionals" {
4437 .source = ".{ .foo = .{} }",4594 .source = ".{ .foo = .{} }",
4438 .errors = &errors,4595 .errors = &errors,
4439 }));4596 }));
4440 try std.testing.expectFmt("1:12: error: missing required field qux\n", "{f}", .{errors});4597 try std.testing.expectFmt(
4598 \\input.zon:1:12: error: missing required field qux
4599 \\
4600 , "{f}", .{errors.fmt("input.zon")});
4441 }4601 }
44424602
4443 // Updating an optional that starts out non-null should preserve any values we leave off. It's4603 // Updating an optional that starts out non-null should preserve any values we leave off. It's
...@@ -4557,7 +4717,10 @@ test "std.zon update unions" {...@@ -4557,7 +4717,10 @@ test "std.zon update unions" {
4557 .source = ".{ .foo = .{} }",4717 .source = ".{ .foo = .{} }",
4558 .errors = &errors,4718 .errors = &errors,
4559 }));4719 }));
4560 try std.testing.expectFmt("1:12: error: missing required field qux\n", "{f}", .{errors});4720 try std.testing.expectFmt(
4721 \\input.zon:1:12: error: missing required field qux
4722 \\
4723 , "{f}", .{errors.fmt("input.zon")});
4561 }4724 }
45624725
4563 // Updating a union should preseve any sub-fields that we left off. It's also okay to leave off4726 // Updating a union should preseve any sub-fields that we left off. It's also okay to leave off