authorgravatar for nick@cern.isNick Cernis <nick@cern.is> 2022-11-12 20:03:24+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-11-12 21:03:24+02:00
log8a5818535b83ba87849cb09de9f1ccd32e8bb480
tree8b63ffe15c08edbe921d17594c5d333219937670
parent32b97df50ea18a194ce9e14b267c99f146a3e2fd
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Make invalidFmtError public and use in place of compileErrors for bad format strings (#13526)

* Export invalidFmtErr To allow consistent use of "invalid format string" compile error response for badly formatted format strings. See https://github.com/ziglang/zig/pull/13489#issuecomment-1311759340. * Replace format compile errors with invalidFmtErr - Provides more consistent compile errors. - Gives user info about the type of the badly formated value. * Rename invalidFmtErr as invalidFmtError For consistency. Zig seems to use “Error” more often than “Err”. * std: add invalid format string checks to remaining custom formatters * pass reference-trace to comp when building build file; fix checkobjectstep

18 files changed, 52 insertions(+), 43 deletions(-)

lib/std/SemanticVersion.zig+1-1
......@@ -157,7 +157,7 @@ pub fn format(
157157 out_stream: anytype,
158158) !void {
159159 _ = options;
160 if (fmt.len != 0) @compileError("Unknown format string: '" ++ fmt ++ "'");
160 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
161161 try std.fmt.format(out_stream, "{d}.{d}.{d}", .{ self.major, self.minor, self.patch });
162162 if (self.pre) |pre| try std.fmt.format(out_stream, "-{s}", .{pre});
163163 if (self.build) |build| try std.fmt.format(out_stream, "+{s}", .{build});
lib/std/build/CheckObjectStep.zig+2-2
......@@ -187,7 +187,7 @@ const ComputeCompareExpected = struct {
187187 options: std.fmt.FormatOptions,
188188 writer: anytype,
189189 ) !void {
190 _ = fmt;
190 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, value);
191191 _ = options;
192192 try writer.print("{s} ", .{@tagName(value.op)});
193193 switch (value.value) {
......@@ -360,7 +360,7 @@ fn make(step: *Step) !void {
360360 std.debug.print(
361361 \\
362362 \\========= Comparison failed for action: ===========
363 \\{s} {s}
363 \\{s} {}
364364 \\========= From parsed file: =======================
365365 \\{s}
366366 \\
lib/std/builtin.zig+3-2
......@@ -38,12 +38,13 @@ pub const StackTrace = struct {
3838 options: std.fmt.FormatOptions,
3939 writer: anytype,
4040 ) !void {
41 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
42
4143 // TODO: re-evaluate whether to use format() methods at all.
4244 // Until then, avoid an error when using GeneralPurposeAllocator with WebAssembly
4345 // where it tries to call detectTTYConfig here.
4446 if (builtin.os.tag == .freestanding) return;
4547
46 _ = fmt;
4748 _ = options;
4849 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
4950 defer arena.deinit();
......@@ -534,7 +535,7 @@ pub const Version = struct {
534535 return std.fmt.format(out_stream, "{d}.{d}.{d}", .{ self.major, self.minor, self.patch });
535536 }
536537 } else {
537 @compileError("Unknown format string: '" ++ fmt ++ "'");
538 std.fmt.invalidFmtError(fmt, self);
538539 }
539540 }
540541};
lib/std/debug.zig+1-1
......@@ -2123,7 +2123,7 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize
21232123 options: std.fmt.FormatOptions,
21242124 writer: anytype,
21252125 ) !void {
2126 _ = fmt;
2126 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, t);
21272127 _ = options;
21282128 if (enabled) {
21292129 try writer.writeAll("\n");
lib/std/fmt.zig+15-15
......@@ -454,7 +454,7 @@ fn stripOptionalOrErrorUnionSpec(comptime fmt: []const u8) []const u8 {
454454 fmt[1..];
455455}
456456
457fn invalidFmtErr(comptime fmt: []const u8, value: anytype) void {
457pub fn invalidFmtError(comptime fmt: []const u8, value: anytype) void {
458458 @compileError("invalid format string '" ++ fmt ++ "' for type '" ++ @typeName(@TypeOf(value)) ++ "'");
459459}
460460
......@@ -486,11 +486,11 @@ pub fn formatType(
486486 return formatValue(value, actual_fmt, options, writer);
487487 },
488488 .Void => {
489 if (actual_fmt.len != 0) invalidFmtErr(fmt, value);
489 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
490490 return formatBuf("void", options, writer);
491491 },
492492 .Bool => {
493 if (actual_fmt.len != 0) invalidFmtErr(fmt, value);
493 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
494494 return formatBuf(if (value) "true" else "false", options, writer);
495495 },
496496 .Optional => {
......@@ -514,14 +514,14 @@ pub fn formatType(
514514 }
515515 },
516516 .ErrorSet => {
517 if (actual_fmt.len != 0) invalidFmtErr(fmt, value);
517 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
518518 try writer.writeAll("error.");
519519 return writer.writeAll(@errorName(value));
520520 },
521521 .Enum => |enumInfo| {
522522 try writer.writeAll(@typeName(T));
523523 if (enumInfo.is_exhaustive) {
524 if (actual_fmt.len != 0) invalidFmtErr(fmt, value);
524 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
525525 try writer.writeAll(".");
526526 try writer.writeAll(@tagName(value));
527527 return;
......@@ -542,7 +542,7 @@ pub fn formatType(
542542 try writer.writeAll(")");
543543 },
544544 .Union => |info| {
545 if (actual_fmt.len != 0) invalidFmtErr(fmt, value);
545 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
546546 try writer.writeAll(@typeName(T));
547547 if (max_depth == 0) {
548548 return writer.writeAll("{ ... }");
......@@ -562,7 +562,7 @@ pub fn formatType(
562562 }
563563 },
564564 .Struct => |info| {
565 if (actual_fmt.len != 0) invalidFmtErr(fmt, value);
565 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
566566 if (info.is_tuple) {
567567 // Skip the type and field names when formatting tuples.
568568 if (max_depth == 0) {
......@@ -618,7 +618,7 @@ pub fn formatType(
618618 }
619619 return;
620620 }
621 invalidFmtErr(fmt, value);
621 invalidFmtError(fmt, value);
622622 },
623623 .Enum, .Union, .Struct => {
624624 return formatType(value.*, actual_fmt, options, writer, max_depth);
......@@ -640,7 +640,7 @@ pub fn formatType(
640640 else => {},
641641 }
642642 }
643 invalidFmtErr(fmt, value);
643 invalidFmtError(fmt, value);
644644 },
645645 .Slice => {
646646 if (actual_fmt.len == 0)
......@@ -703,20 +703,20 @@ pub fn formatType(
703703 try writer.writeAll(" }");
704704 },
705705 .Fn => {
706 if (actual_fmt.len != 0) invalidFmtErr(fmt, value);
706 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
707707 return format(writer, "{s}@{x}", .{ @typeName(T), @ptrToInt(value) });
708708 },
709709 .Type => {
710 if (actual_fmt.len != 0) invalidFmtErr(fmt, value);
710 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
711711 return formatBuf(@typeName(value), options, writer);
712712 },
713713 .EnumLiteral => {
714 if (actual_fmt.len != 0) invalidFmtErr(fmt, value);
714 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
715715 const buffer = [_]u8{'.'} ++ @tagName(value);
716716 return formatBuf(buffer, options, writer);
717717 },
718718 .Null => {
719 if (actual_fmt.len != 0) invalidFmtErr(fmt, value);
719 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
720720 return formatBuf("null", options, writer);
721721 },
722722 else => @compileError("unable to format type '" ++ @typeName(T) ++ "'"),
......@@ -786,7 +786,7 @@ pub fn formatIntValue(
786786 radix = 8;
787787 case = .lower;
788788 } else {
789 invalidFmtErr(fmt, value);
789 invalidFmtError(fmt, value);
790790 }
791791
792792 return formatInt(int_value, radix, case, options, writer);
......@@ -815,7 +815,7 @@ fn formatFloatValue(
815815 error.NoSpaceLeft => unreachable,
816816 };
817817 } else {
818 invalidFmtErr(fmt, value);
818 invalidFmtError(fmt, value);
819819 }
820820
821821 return formatBuf(buf_stream.getWritten(), options, writer);
lib/std/fs/wasi.zig+1-1
......@@ -62,7 +62,7 @@ pub const PreopenType = union(PreopenTypeTag) {
6262 }
6363
6464 pub fn format(self: Self, comptime fmt: []const u8, options: std.fmt.FormatOptions, out_stream: anytype) !void {
65 _ = fmt;
65 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
6666 _ = options;
6767 try out_stream.print("PreopenType{{ ", .{});
6868 switch (self) {
lib/std/heap/general_purpose_allocator.zig+5-5
......@@ -326,7 +326,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
326326 const slot_index = @intCast(SlotIndex, used_bits_byte * 8 + bit_index);
327327 const stack_trace = bucketStackTrace(bucket, size_class, slot_index, .alloc);
328328 const addr = bucket.page + slot_index * size_class;
329 log.err("memory address 0x{x} leaked: {s}", .{
329 log.err("memory address 0x{x} leaked: {}", .{
330330 @ptrToInt(addr), stack_trace,
331331 });
332332 leaks = true;
......@@ -358,7 +358,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
358358 while (it.next()) |large_alloc| {
359359 if (config.retain_metadata and large_alloc.freed) continue;
360360 const stack_trace = large_alloc.getStackTrace(.alloc);
361 log.err("memory address 0x{x} leaked: {s}", .{
361 log.err("memory address 0x{x} leaked: {}", .{
362362 @ptrToInt(large_alloc.bytes.ptr), stack_trace,
363363 });
364364 leaks = true;
......@@ -443,7 +443,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
443443 .index = 0,
444444 };
445445 std.debug.captureStackTrace(ret_addr, &second_free_stack_trace);
446 log.err("Double free detected. Allocation: {s} First free: {s} Second free: {s}", .{
446 log.err("Double free detected. Allocation: {} First free: {} Second free: {}", .{
447447 alloc_stack_trace, free_stack_trace, second_free_stack_trace,
448448 });
449449 }
......@@ -533,7 +533,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
533533 .index = 0,
534534 };
535535 std.debug.captureStackTrace(ret_addr, &free_stack_trace);
536 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {s} Free: {s}", .{
536 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {} Free: {}", .{
537537 entry.value_ptr.bytes.len,
538538 old_mem.len,
539539 entry.value_ptr.getStackTrace(.alloc),
......@@ -606,7 +606,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
606606 .index = 0,
607607 };
608608 std.debug.captureStackTrace(ret_addr, &free_stack_trace);
609 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {s} Free: {s}", .{
609 log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {} Free: {}", .{
610610 entry.value_ptr.bytes.len,
611611 old_mem.len,
612612 entry.value_ptr.getStackTrace(.alloc),
lib/std/math/big/int.zig+1-1
......@@ -2061,7 +2061,7 @@ pub const Const = struct {
20612061 radix = 16;
20622062 case = .upper;
20632063 } else {
2064 @compileError("Unknown format string: '" ++ fmt ++ "'");
2064 std.fmt.invalidFmtError(fmt, self);
20652065 }
20662066
20672067 var limbs: [128]Limb = undefined;
lib/std/net.zig+3-2
......@@ -149,6 +149,7 @@ pub const Address = extern union {
149149 options: std.fmt.FormatOptions,
150150 out_stream: anytype,
151151 ) !void {
152 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
152153 switch (self.any.family) {
153154 os.AF.INET => try self.in.format(fmt, options, out_stream),
154155 os.AF.INET6 => try self.in6.format(fmt, options, out_stream),
......@@ -274,7 +275,7 @@ pub const Ip4Address = extern struct {
274275 options: std.fmt.FormatOptions,
275276 out_stream: anytype,
276277 ) !void {
277 _ = fmt;
278 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
278279 _ = options;
279280 const bytes = @ptrCast(*const [4]u8, &self.sa.addr);
280281 try std.fmt.format(out_stream, "{}.{}.{}.{}:{}", .{
......@@ -563,7 +564,7 @@ pub const Ip6Address = extern struct {
563564 options: std.fmt.FormatOptions,
564565 out_stream: anytype,
565566 ) !void {
566 _ = fmt;
567 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
567568 _ = options;
568569 const port = mem.bigToNative(u16, self.sa.port);
569570 if (mem.eql(u8, self.sa.addr[0..12], &[_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff })) {
lib/std/os/uefi.zig+1-1
......@@ -68,7 +68,7 @@ pub const Guid = extern struct {
6868 fmt(std.mem.asBytes(&self.node)),
6969 });
7070 } else {
71 @compileError("Unknown format character: '" ++ f ++ "'");
71 std.fmt.invalidFmtError(f, self);
7272 }
7373 }
7474
lib/std/target.zig+4-2
......@@ -167,19 +167,21 @@ pub const Target = struct {
167167 _: std.fmt.FormatOptions,
168168 out_stream: anytype,
169169 ) !void {
170 if (fmt.len > 0 and fmt[0] == 's') {
170 if (comptime std.mem.eql(u8, fmt, "s")) {
171171 if (@enumToInt(self) >= @enumToInt(WindowsVersion.nt4) and @enumToInt(self) <= @enumToInt(WindowsVersion.latest)) {
172172 try std.fmt.format(out_stream, ".{s}", .{@tagName(self)});
173173 } else {
174174 // TODO this code path breaks zig triples, but it is used in `builtin`
175175 try std.fmt.format(out_stream, "@intToEnum(Target.Os.WindowsVersion, 0x{X:0>8})", .{@enumToInt(self)});
176176 }
177 } else {
177 } else if (fmt.len == 0) {
178178 if (@enumToInt(self) >= @enumToInt(WindowsVersion.nt4) and @enumToInt(self) <= @enumToInt(WindowsVersion.latest)) {
179179 try std.fmt.format(out_stream, "WindowsVersion.{s}", .{@tagName(self)});
180180 } else {
181181 try std.fmt.format(out_stream, "WindowsVersion(0x{X:0>8})", .{@enumToInt(self)});
182182 }
183 } else {
184 std.fmt.invalidFmtError(fmt, self);
183185 }
184186 }
185187 };
lib/std/testing.zig+1-1
......@@ -700,7 +700,7 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime
700700 error.OutOfMemory => {
701701 if (failing_allocator_inst.allocated_bytes != failing_allocator_inst.freed_bytes) {
702702 print(
703 "\nfail_index: {d}/{d}\nallocated bytes: {d}\nfreed bytes: {d}\nallocations: {d}\ndeallocations: {d}\nallocation that was made to fail: {s}",
703 "\nfail_index: {d}/{d}\nallocated bytes: {d}\nfreed bytes: {d}\nallocations: {d}\ndeallocations: {d}\nallocation that was made to fail: {}",
704704 .{
705705 fail_index,
706706 needed_alloc_count,
lib/std/wasm.zig+1-1
......@@ -356,7 +356,7 @@ pub const Type = struct {
356356 returns: []const Valtype,
357357
358358 pub fn format(self: Type, comptime fmt: []const u8, opt: std.fmt.FormatOptions, writer: anytype) !void {
359 _ = fmt;
359 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
360360 _ = opt;
361361 try writer.writeByte('(');
362362 for (self.params) |param, i| {
lib/std/x/net/bpf.zig+1-2
......@@ -282,8 +282,7 @@ pub const Insn = extern struct {
282282 writer: anytype,
283283 ) !void {
284284 _ = opts;
285 if (comptime layout.len != 0 and layout[0] != 's')
286 @compileError("Unsupported format specifier for BPF Insn type '" ++ layout ++ "'.");
285 if (layout.len != 0) std.fmt.invalidFmtError(layout, self);
287286
288287 try std.fmt.format(
289288 writer,
lib/std/x/net/ip.zig+1-1
......@@ -47,8 +47,8 @@ pub const Address = union(enum) {
4747 opts: fmt.FormatOptions,
4848 writer: anytype,
4949 ) !void {
50 if (layout.len != 0) std.fmt.invalidFmtError(layout, self);
5051 _ = opts;
51 _ = layout;
5252 switch (self) {
5353 .ipv4 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }),
5454 .ipv6 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }),
lib/std/x/os/net.zig+2-4
......@@ -168,9 +168,7 @@ pub const IPv4 = extern struct {
168168 writer: anytype,
169169 ) !void {
170170 _ = opts;
171 if (comptime layout.len != 0 and layout[0] != 's') {
172 @compileError("Unsupported format specifier for IPv4 type '" ++ layout ++ "'.");
173 }
171 if (layout.len != 0) std.fmt.invalidFmtError(layout, self);
174172
175173 try fmt.format(writer, "{}.{}.{}.{}", .{
176174 self.octets[0],
......@@ -382,7 +380,7 @@ pub const IPv6 = extern struct {
382380 'x', 'X' => |specifier| specifier,
383381 's' => 'x',
384382 'S' => 'X',
385 else => @compileError("Unsupported format specifier for IPv6 type '" ++ layout ++ "'."),
383 else => std.fmt.invalidFmtError(layout, self),
386384 }};
387385
388386 if (mem.startsWith(u8, &self.octets, &v4_mapped_prefix)) {
lib/std/x/os/socket.zig+1-1
......@@ -127,8 +127,8 @@ pub const Socket = struct {
127127 opts: fmt.FormatOptions,
128128 writer: anytype,
129129 ) !void {
130 if (layout.len != 0) std.fmt.invalidFmtError(layout, self);
130131 _ = opts;
131 _ = layout;
132132 switch (self) {
133133 .ipv4 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }),
134134 .ipv6 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }),
src/main.zig+8
......@@ -3744,6 +3744,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
37443744 var override_global_cache_dir: ?[]const u8 = try optionalStringEnvVar(arena, "ZIG_GLOBAL_CACHE_DIR");
37453745 var override_local_cache_dir: ?[]const u8 = try optionalStringEnvVar(arena, "ZIG_LOCAL_CACHE_DIR");
37463746 var child_argv = std.ArrayList([]const u8).init(arena);
3747 var reference_trace: ?u32 = null;
37473748
37483749 const argv_index_exe = child_argv.items.len;
37493750 _ = try child_argv.addOne();
......@@ -3795,10 +3796,16 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
37953796 try child_argv.append(arg);
37963797 } else if (mem.eql(u8, arg, "-freference-trace")) {
37973798 try child_argv.append(arg);
3799 reference_trace = 256;
37983800 } else if (mem.startsWith(u8, arg, "-freference-trace=")) {
37993801 try child_argv.append(arg);
3802 const num = arg["-freference-trace=".len..];
3803 reference_trace = std.fmt.parseUnsigned(u32, num, 10) catch |err| {
3804 fatal("unable to parse reference_trace count '{s}': {s}", .{ num, @errorName(err) });
3805 };
38003806 } else if (mem.eql(u8, arg, "-fno-reference-trace")) {
38013807 try child_argv.append(arg);
3808 reference_trace = null;
38023809 }
38033810 }
38043811 try child_argv.append(arg);
......@@ -3932,6 +3939,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
39323939 .thread_pool = &thread_pool,
39333940 .use_stage1 = use_stage1,
39343941 .cache_mode = .whole,
3942 .reference_trace = reference_trace,
39353943 }) catch |err| {
39363944 fatal("unable to create compilation: {s}", .{@errorName(err)});
39373945 };