diff --git a/lib/std/SemanticVersion.zig b/lib/std/SemanticVersion.zig index cd0d48fba7..99072eeea5 100644 --- a/lib/std/SemanticVersion.zig +++ b/lib/std/SemanticVersion.zig @@ -157,7 +157,7 @@ pub fn format( out_stream: anytype, ) !void { _ = options; - if (fmt.len != 0) @compileError("Unknown format string: '" ++ fmt ++ "'"); + if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self); try std.fmt.format(out_stream, "{d}.{d}.{d}", .{ self.major, self.minor, self.patch }); if (self.pre) |pre| try std.fmt.format(out_stream, "-{s}", .{pre}); if (self.build) |build| try std.fmt.format(out_stream, "+{s}", .{build}); diff --git a/lib/std/build/CheckObjectStep.zig b/lib/std/build/CheckObjectStep.zig index 63b361473b..7bebea54a0 100644 --- a/lib/std/build/CheckObjectStep.zig +++ b/lib/std/build/CheckObjectStep.zig @@ -187,7 +187,7 @@ const ComputeCompareExpected = struct { options: std.fmt.FormatOptions, writer: anytype, ) !void { - _ = fmt; + if (fmt.len != 0) std.fmt.invalidFmtError(fmt, value); _ = options; try writer.print("{s} ", .{@tagName(value.op)}); switch (value.value) { @@ -360,7 +360,7 @@ fn make(step: *Step) !void { std.debug.print( \\ \\========= Comparison failed for action: =========== - \\{s} {s} + \\{s} {} \\========= From parsed file: ======================= \\{s} \\ diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index 430a29c9d7..33604dfee7 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -38,12 +38,13 @@ pub const StackTrace = struct { options: std.fmt.FormatOptions, writer: anytype, ) !void { + if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self); + // TODO: re-evaluate whether to use format() methods at all. // Until then, avoid an error when using GeneralPurposeAllocator with WebAssembly // where it tries to call detectTTYConfig here. if (builtin.os.tag == .freestanding) return; - _ = fmt; _ = options; var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit(); @@ -534,7 +535,7 @@ pub const Version = struct { return std.fmt.format(out_stream, "{d}.{d}.{d}", .{ self.major, self.minor, self.patch }); } } else { - @compileError("Unknown format string: '" ++ fmt ++ "'"); + std.fmt.invalidFmtError(fmt, self); } } }; diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 205be60b11..75e8426e2c 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -2123,7 +2123,7 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize options: std.fmt.FormatOptions, writer: anytype, ) !void { - _ = fmt; + if (fmt.len != 0) std.fmt.invalidFmtError(fmt, t); _ = options; if (enabled) { try writer.writeAll("\n"); diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 0fcb2ae5b1..2af293194a 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -454,7 +454,7 @@ fn stripOptionalOrErrorUnionSpec(comptime fmt: []const u8) []const u8 { fmt[1..]; } -fn invalidFmtErr(comptime fmt: []const u8, value: anytype) void { +pub fn invalidFmtError(comptime fmt: []const u8, value: anytype) void { @compileError("invalid format string '" ++ fmt ++ "' for type '" ++ @typeName(@TypeOf(value)) ++ "'"); } @@ -486,11 +486,11 @@ pub fn formatType( return formatValue(value, actual_fmt, options, writer); }, .Void => { - if (actual_fmt.len != 0) invalidFmtErr(fmt, value); + if (actual_fmt.len != 0) invalidFmtError(fmt, value); return formatBuf("void", options, writer); }, .Bool => { - if (actual_fmt.len != 0) invalidFmtErr(fmt, value); + if (actual_fmt.len != 0) invalidFmtError(fmt, value); return formatBuf(if (value) "true" else "false", options, writer); }, .Optional => { @@ -514,14 +514,14 @@ pub fn formatType( } }, .ErrorSet => { - if (actual_fmt.len != 0) invalidFmtErr(fmt, value); + if (actual_fmt.len != 0) invalidFmtError(fmt, value); try writer.writeAll("error."); return writer.writeAll(@errorName(value)); }, .Enum => |enumInfo| { try writer.writeAll(@typeName(T)); if (enumInfo.is_exhaustive) { - if (actual_fmt.len != 0) invalidFmtErr(fmt, value); + if (actual_fmt.len != 0) invalidFmtError(fmt, value); try writer.writeAll("."); try writer.writeAll(@tagName(value)); return; @@ -542,7 +542,7 @@ pub fn formatType( try writer.writeAll(")"); }, .Union => |info| { - if (actual_fmt.len != 0) invalidFmtErr(fmt, value); + if (actual_fmt.len != 0) invalidFmtError(fmt, value); try writer.writeAll(@typeName(T)); if (max_depth == 0) { return writer.writeAll("{ ... }"); @@ -562,7 +562,7 @@ pub fn formatType( } }, .Struct => |info| { - if (actual_fmt.len != 0) invalidFmtErr(fmt, value); + if (actual_fmt.len != 0) invalidFmtError(fmt, value); if (info.is_tuple) { // Skip the type and field names when formatting tuples. if (max_depth == 0) { @@ -618,7 +618,7 @@ pub fn formatType( } return; } - invalidFmtErr(fmt, value); + invalidFmtError(fmt, value); }, .Enum, .Union, .Struct => { return formatType(value.*, actual_fmt, options, writer, max_depth); @@ -640,7 +640,7 @@ pub fn formatType( else => {}, } } - invalidFmtErr(fmt, value); + invalidFmtError(fmt, value); }, .Slice => { if (actual_fmt.len == 0) @@ -703,20 +703,20 @@ pub fn formatType( try writer.writeAll(" }"); }, .Fn => { - if (actual_fmt.len != 0) invalidFmtErr(fmt, value); + if (actual_fmt.len != 0) invalidFmtError(fmt, value); return format(writer, "{s}@{x}", .{ @typeName(T), @ptrToInt(value) }); }, .Type => { - if (actual_fmt.len != 0) invalidFmtErr(fmt, value); + if (actual_fmt.len != 0) invalidFmtError(fmt, value); return formatBuf(@typeName(value), options, writer); }, .EnumLiteral => { - if (actual_fmt.len != 0) invalidFmtErr(fmt, value); + if (actual_fmt.len != 0) invalidFmtError(fmt, value); const buffer = [_]u8{'.'} ++ @tagName(value); return formatBuf(buffer, options, writer); }, .Null => { - if (actual_fmt.len != 0) invalidFmtErr(fmt, value); + if (actual_fmt.len != 0) invalidFmtError(fmt, value); return formatBuf("null", options, writer); }, else => @compileError("unable to format type '" ++ @typeName(T) ++ "'"), @@ -786,7 +786,7 @@ pub fn formatIntValue( radix = 8; case = .lower; } else { - invalidFmtErr(fmt, value); + invalidFmtError(fmt, value); } return formatInt(int_value, radix, case, options, writer); @@ -815,7 +815,7 @@ fn formatFloatValue( error.NoSpaceLeft => unreachable, }; } else { - invalidFmtErr(fmt, value); + invalidFmtError(fmt, value); } return formatBuf(buf_stream.getWritten(), options, writer); diff --git a/lib/std/fs/wasi.zig b/lib/std/fs/wasi.zig index 522731ef02..ca766bbd29 100644 --- a/lib/std/fs/wasi.zig +++ b/lib/std/fs/wasi.zig @@ -62,7 +62,7 @@ pub const PreopenType = union(PreopenTypeTag) { } pub fn format(self: Self, comptime fmt: []const u8, options: std.fmt.FormatOptions, out_stream: anytype) !void { - _ = fmt; + if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self); _ = options; try out_stream.print("PreopenType{{ ", .{}); switch (self) { diff --git a/lib/std/heap/general_purpose_allocator.zig b/lib/std/heap/general_purpose_allocator.zig index 2180b87942..11bc9d0d11 100644 --- a/lib/std/heap/general_purpose_allocator.zig +++ b/lib/std/heap/general_purpose_allocator.zig @@ -326,7 +326,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { const slot_index = @intCast(SlotIndex, used_bits_byte * 8 + bit_index); const stack_trace = bucketStackTrace(bucket, size_class, slot_index, .alloc); const addr = bucket.page + slot_index * size_class; - log.err("memory address 0x{x} leaked: {s}", .{ + log.err("memory address 0x{x} leaked: {}", .{ @ptrToInt(addr), stack_trace, }); leaks = true; @@ -358,7 +358,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { while (it.next()) |large_alloc| { if (config.retain_metadata and large_alloc.freed) continue; const stack_trace = large_alloc.getStackTrace(.alloc); - log.err("memory address 0x{x} leaked: {s}", .{ + log.err("memory address 0x{x} leaked: {}", .{ @ptrToInt(large_alloc.bytes.ptr), stack_trace, }); leaks = true; @@ -443,7 +443,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { .index = 0, }; std.debug.captureStackTrace(ret_addr, &second_free_stack_trace); - log.err("Double free detected. Allocation: {s} First free: {s} Second free: {s}", .{ + log.err("Double free detected. Allocation: {} First free: {} Second free: {}", .{ alloc_stack_trace, free_stack_trace, second_free_stack_trace, }); } @@ -533,7 +533,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { .index = 0, }; std.debug.captureStackTrace(ret_addr, &free_stack_trace); - log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {s} Free: {s}", .{ + log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {} Free: {}", .{ entry.value_ptr.bytes.len, old_mem.len, entry.value_ptr.getStackTrace(.alloc), @@ -606,7 +606,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { .index = 0, }; std.debug.captureStackTrace(ret_addr, &free_stack_trace); - log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {s} Free: {s}", .{ + log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {} Free: {}", .{ entry.value_ptr.bytes.len, old_mem.len, entry.value_ptr.getStackTrace(.alloc), diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index ac2f089ea1..189093aa84 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -2061,7 +2061,7 @@ pub const Const = struct { radix = 16; case = .upper; } else { - @compileError("Unknown format string: '" ++ fmt ++ "'"); + std.fmt.invalidFmtError(fmt, self); } var limbs: [128]Limb = undefined; diff --git a/lib/std/net.zig b/lib/std/net.zig index 21fa36c4eb..def6e0e46f 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -149,6 +149,7 @@ pub const Address = extern union { options: std.fmt.FormatOptions, out_stream: anytype, ) !void { + if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self); switch (self.any.family) { os.AF.INET => try self.in.format(fmt, options, out_stream), os.AF.INET6 => try self.in6.format(fmt, options, out_stream), @@ -274,7 +275,7 @@ pub const Ip4Address = extern struct { options: std.fmt.FormatOptions, out_stream: anytype, ) !void { - _ = fmt; + if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self); _ = options; const bytes = @ptrCast(*const [4]u8, &self.sa.addr); try std.fmt.format(out_stream, "{}.{}.{}.{}:{}", .{ @@ -563,7 +564,7 @@ pub const Ip6Address = extern struct { options: std.fmt.FormatOptions, out_stream: anytype, ) !void { - _ = fmt; + if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self); _ = options; const port = mem.bigToNative(u16, self.sa.port); if (mem.eql(u8, self.sa.addr[0..12], &[_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff })) { diff --git a/lib/std/os/uefi.zig b/lib/std/os/uefi.zig index 25964e09fa..f51caaa86f 100644 --- a/lib/std/os/uefi.zig +++ b/lib/std/os/uefi.zig @@ -68,7 +68,7 @@ pub const Guid = extern struct { fmt(std.mem.asBytes(&self.node)), }); } else { - @compileError("Unknown format character: '" ++ f ++ "'"); + std.fmt.invalidFmtError(f, self); } } diff --git a/lib/std/target.zig b/lib/std/target.zig index cbab23644b..745be7dbff 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -167,19 +167,21 @@ pub const Target = struct { _: std.fmt.FormatOptions, out_stream: anytype, ) !void { - if (fmt.len > 0 and fmt[0] == 's') { + if (comptime std.mem.eql(u8, fmt, "s")) { if (@enumToInt(self) >= @enumToInt(WindowsVersion.nt4) and @enumToInt(self) <= @enumToInt(WindowsVersion.latest)) { try std.fmt.format(out_stream, ".{s}", .{@tagName(self)}); } else { // TODO this code path breaks zig triples, but it is used in `builtin` try std.fmt.format(out_stream, "@intToEnum(Target.Os.WindowsVersion, 0x{X:0>8})", .{@enumToInt(self)}); } - } else { + } else if (fmt.len == 0) { if (@enumToInt(self) >= @enumToInt(WindowsVersion.nt4) and @enumToInt(self) <= @enumToInt(WindowsVersion.latest)) { try std.fmt.format(out_stream, "WindowsVersion.{s}", .{@tagName(self)}); } else { try std.fmt.format(out_stream, "WindowsVersion(0x{X:0>8})", .{@enumToInt(self)}); } + } else { + std.fmt.invalidFmtError(fmt, self); } } }; diff --git a/lib/std/testing.zig b/lib/std/testing.zig index 60a778ad7a..f1b01b0bd0 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -700,7 +700,7 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime error.OutOfMemory => { if (failing_allocator_inst.allocated_bytes != failing_allocator_inst.freed_bytes) { print( - "\nfail_index: {d}/{d}\nallocated bytes: {d}\nfreed bytes: {d}\nallocations: {d}\ndeallocations: {d}\nallocation that was made to fail: {s}", + "\nfail_index: {d}/{d}\nallocated bytes: {d}\nfreed bytes: {d}\nallocations: {d}\ndeallocations: {d}\nallocation that was made to fail: {}", .{ fail_index, needed_alloc_count, diff --git a/lib/std/wasm.zig b/lib/std/wasm.zig index 9af0156239..3d47d43487 100644 --- a/lib/std/wasm.zig +++ b/lib/std/wasm.zig @@ -356,7 +356,7 @@ pub const Type = struct { returns: []const Valtype, pub fn format(self: Type, comptime fmt: []const u8, opt: std.fmt.FormatOptions, writer: anytype) !void { - _ = fmt; + if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self); _ = opt; try writer.writeByte('('); for (self.params) |param, i| { diff --git a/lib/std/x/net/bpf.zig b/lib/std/x/net/bpf.zig index 8fd318b03b..bee930c332 100644 --- a/lib/std/x/net/bpf.zig +++ b/lib/std/x/net/bpf.zig @@ -282,8 +282,7 @@ pub const Insn = extern struct { writer: anytype, ) !void { _ = opts; - if (comptime layout.len != 0 and layout[0] != 's') - @compileError("Unsupported format specifier for BPF Insn type '" ++ layout ++ "'."); + if (layout.len != 0) std.fmt.invalidFmtError(layout, self); try std.fmt.format( writer, diff --git a/lib/std/x/net/ip.zig b/lib/std/x/net/ip.zig index a3f5dfecf6..b3da9725d8 100644 --- a/lib/std/x/net/ip.zig +++ b/lib/std/x/net/ip.zig @@ -47,8 +47,8 @@ pub const Address = union(enum) { opts: fmt.FormatOptions, writer: anytype, ) !void { + if (layout.len != 0) std.fmt.invalidFmtError(layout, self); _ = opts; - _ = layout; switch (self) { .ipv4 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }), .ipv6 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }), diff --git a/lib/std/x/os/net.zig b/lib/std/x/os/net.zig index d8af2b3577..e00299e243 100644 --- a/lib/std/x/os/net.zig +++ b/lib/std/x/os/net.zig @@ -168,9 +168,7 @@ pub const IPv4 = extern struct { writer: anytype, ) !void { _ = opts; - if (comptime layout.len != 0 and layout[0] != 's') { - @compileError("Unsupported format specifier for IPv4 type '" ++ layout ++ "'."); - } + if (layout.len != 0) std.fmt.invalidFmtError(layout, self); try fmt.format(writer, "{}.{}.{}.{}", .{ self.octets[0], @@ -382,7 +380,7 @@ pub const IPv6 = extern struct { 'x', 'X' => |specifier| specifier, 's' => 'x', 'S' => 'X', - else => @compileError("Unsupported format specifier for IPv6 type '" ++ layout ++ "'."), + else => std.fmt.invalidFmtError(layout, self), }}; if (mem.startsWith(u8, &self.octets, &v4_mapped_prefix)) { diff --git a/lib/std/x/os/socket.zig b/lib/std/x/os/socket.zig index ed354681ed..3de9359cc5 100644 --- a/lib/std/x/os/socket.zig +++ b/lib/std/x/os/socket.zig @@ -127,8 +127,8 @@ pub const Socket = struct { opts: fmt.FormatOptions, writer: anytype, ) !void { + if (layout.len != 0) std.fmt.invalidFmtError(layout, self); _ = opts; - _ = layout; switch (self) { .ipv4 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }), .ipv6 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }), diff --git a/src/main.zig b/src/main.zig index d0edbbed6d..71325b18d9 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3744,6 +3744,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi var override_global_cache_dir: ?[]const u8 = try optionalStringEnvVar(arena, "ZIG_GLOBAL_CACHE_DIR"); var override_local_cache_dir: ?[]const u8 = try optionalStringEnvVar(arena, "ZIG_LOCAL_CACHE_DIR"); var child_argv = std.ArrayList([]const u8).init(arena); + var reference_trace: ?u32 = null; const argv_index_exe = child_argv.items.len; _ = try child_argv.addOne(); @@ -3795,10 +3796,16 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi try child_argv.append(arg); } else if (mem.eql(u8, arg, "-freference-trace")) { try child_argv.append(arg); + reference_trace = 256; } else if (mem.startsWith(u8, arg, "-freference-trace=")) { try child_argv.append(arg); + const num = arg["-freference-trace=".len..]; + reference_trace = std.fmt.parseUnsigned(u32, num, 10) catch |err| { + fatal("unable to parse reference_trace count '{s}': {s}", .{ num, @errorName(err) }); + }; } else if (mem.eql(u8, arg, "-fno-reference-trace")) { try child_argv.append(arg); + reference_trace = null; } } try child_argv.append(arg); @@ -3932,6 +3939,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi .thread_pool = &thread_pool, .use_stage1 = use_stage1, .cache_mode = .whole, + .reference_trace = reference_trace, }) catch |err| { fatal("unable to create compilation: {s}", .{@errorName(err)}); };