std.fmt.format: use {t} for tag name rather than {s}

prevents footgun when formatted type changes from string to enum
This commit is contained in:
Andrew Kelley 2025-07-03 18:50:16 -07:00
parent 30c2921eb8
commit 9c8aef55b4
12 changed files with 39 additions and 29 deletions

View File

@ -67,6 +67,9 @@ pub const Options = struct {
/// - `s`: /// - `s`:
/// - for pointer-to-many and C pointers of u8, print as a C-string using zero-termination /// - for pointer-to-many and C pointers of u8, print as a C-string using zero-termination
/// - for slices of u8, print the entire slice as a string without zero-termination /// - for slices of u8, print the entire slice as a string without zero-termination
/// - `t`:
/// - for enums and tagged unions: prints the tag name
/// - for error sets: prints the error name
/// - `b64`: output string as standard base64 /// - `b64`: output string as standard base64
/// - `e`: output floating point value in scientific notation /// - `e`: output floating point value in scientific notation
/// - `d`: output numeric value in decimal notation /// - `d`: output numeric value in decimal notation

View File

@ -851,12 +851,12 @@ pub fn printValue(
} }
}, },
.error_set => { .error_set => {
if (fmt.len == 1 and fmt[0] == 's') return w.writeAll(@errorName(value)); if (fmt.len == 1 and fmt[0] == 't') return w.writeAll(@errorName(value));
if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
try printErrorSet(w, value); try printErrorSet(w, value);
}, },
.@"enum" => { .@"enum" => {
if (fmt.len == 1 and fmt[0] == 's') { if (fmt.len == 1 and fmt[0] == 't') {
try w.writeAll(@tagName(value)); try w.writeAll(@tagName(value));
return; return;
} }
@ -881,7 +881,7 @@ pub fn printValue(
return; return;
}, },
.@"union" => |info| { .@"union" => |info| {
if (fmt.len == 1 and fmt[0] == 's') { if (fmt.len == 1 and fmt[0] == 't') {
try w.writeAll(@tagName(value)); try w.writeAll(@tagName(value));
return; return;
} }

View File

@ -1265,7 +1265,7 @@ pub const Attribute = union(Kind) {
try w.writeByte(')'); try w.writeByte(')');
}, },
.alignstack => |alignment| { .alignstack => |alignment| {
try w.print(" {s}", .{attribute}); try w.print(" {t}", .{attribute});
const alignment_bytes = alignment.toByteUnits() orelse return; const alignment_bytes = alignment.toByteUnits() orelse return;
if (data.flags.pound) { if (data.flags.pound) {
try w.print("={d}", .{alignment_bytes}); try w.print("={d}", .{alignment_bytes});
@ -1274,7 +1274,7 @@ pub const Attribute = union(Kind) {
} }
}, },
.allockind => |allockind| { .allockind => |allockind| {
try w.print(" {s}(\"", .{@tagName(attribute)}); try w.print(" {t}(\"", .{attribute});
var any = false; var any = false;
inline for (@typeInfo(AllocKind).@"struct".fields) |field| { inline for (@typeInfo(AllocKind).@"struct".fields) |field| {
if (comptime std.mem.eql(u8, field.name, "_")) continue; if (comptime std.mem.eql(u8, field.name, "_")) continue;
@ -1289,13 +1289,13 @@ pub const Attribute = union(Kind) {
try w.writeAll("\")"); try w.writeAll("\")");
}, },
.allocsize => |allocsize| { .allocsize => |allocsize| {
try w.print(" {s}({d}", .{ @tagName(attribute), allocsize.elem_size }); try w.print(" {t}({d}", .{ attribute, allocsize.elem_size });
if (allocsize.num_elems != AllocSize.none) if (allocsize.num_elems != AllocSize.none)
try w.print(",{d}", .{allocsize.num_elems}); try w.print(",{d}", .{allocsize.num_elems});
try w.writeByte(')'); try w.writeByte(')');
}, },
.memory => |memory| { .memory => |memory| {
try w.print(" {s}(", .{@tagName(attribute)}); try w.print(" {t}(", .{attribute});
var any = memory.other != .none or var any = memory.other != .none or
(memory.argmem == .none and memory.inaccessiblemem == .none); (memory.argmem == .none and memory.inaccessiblemem == .none);
if (any) try w.writeAll(@tagName(memory.other)); if (any) try w.writeAll(@tagName(memory.other));
@ -8445,7 +8445,7 @@ pub const Metadata = enum(u32) {
} }
fmt_str = fmt_str ++ "("; fmt_str = fmt_str ++ "(";
inline for (fields[2..], names) |*field, name| { inline for (fields[2..], names) |*field, name| {
fmt_str = fmt_str ++ "{[" ++ name ++ "]fS}"; fmt_str = fmt_str ++ "{[" ++ name ++ "]f}";
field.* = .{ field.* = .{
.name = name, .name = name,
.type = std.fmt.Formatter(FormatData, format), .type = std.fmt.Formatter(FormatData, format),

View File

@ -11406,7 +11406,7 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)
var it = instances.iterator(); var it = instances.iterator();
while (it.next()) |entry| { while (it.next()) |entry| {
const generic_fn_owner_nav = ip.getNav(ip.funcDeclInfo(entry.key_ptr.*).owner_nav); const generic_fn_owner_nav = ip.getNav(ip.funcDeclInfo(entry.key_ptr.*).owner_nav);
try stderr_bw.print("{f} ({f}): \n", .{ generic_fn_owner_nav.name.fmt(ip), entry.value_ptr.items.len }); try stderr_bw.print("{f} ({d}): \n", .{ generic_fn_owner_nav.name.fmt(ip), entry.value_ptr.items.len });
for (entry.value_ptr.items) |index| { for (entry.value_ptr.items) |index| {
const unwrapped_index = index.unwrap(ip); const unwrapped_index = index.unwrap(ip);
const func = ip.extraFuncInstance(unwrapped_index.tid, unwrapped_index.getExtra(ip), unwrapped_index.getData(ip)); const func = ip.extraFuncInstance(unwrapped_index.tid, unwrapped_index.getExtra(ip), unwrapped_index.getData(ip));

View File

@ -20465,7 +20465,7 @@ fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
const is_vector = operand_ty.zigTypeTag(zcu) == .vector; const is_vector = operand_ty.zigTypeTag(zcu) == .vector;
const operand_scalar_ty = operand_ty.scalarType(zcu); const operand_scalar_ty = operand_ty.scalarType(zcu);
if (operand_scalar_ty.toIntern() != .bool_type) { if (operand_scalar_ty.toIntern() != .bool_type) {
return sema.fail(block, src, "expected 'bool', found '{s}'", .{operand_scalar_ty.zigTypeTag(zcu)}); return sema.fail(block, src, "expected 'bool', found '{t}'", .{operand_scalar_ty.zigTypeTag(zcu)});
} }
const len = if (is_vector) operand_ty.vectorLen(zcu) else undefined; const len = if (is_vector) operand_ty.vectorLen(zcu) else undefined;
const dest_ty: Type = if (is_vector) try pt.vectorType(.{ .child = .u1_type, .len = len }) else .u1; const dest_ty: Type = if (is_vector) try pt.vectorType(.{ .child = .u1_type, .len = len }) else .u1;
@ -23576,7 +23576,7 @@ fn checkNumericType(
.comptime_float, .float, .comptime_int, .int => {}, .comptime_float, .float, .comptime_int, .int => {},
.vector => switch (ty.childType(zcu).zigTypeTag(zcu)) { .vector => switch (ty.childType(zcu).zigTypeTag(zcu)) {
.comptime_float, .float, .comptime_int, .int => {}, .comptime_float, .float, .comptime_int, .int => {},
else => |t| return sema.fail(block, ty_src, "expected number, found '{s}'", .{t}), else => |t| return sema.fail(block, ty_src, "expected number, found '{t}'", .{t}),
}, },
else => return sema.fail(block, ty_src, "expected number, found '{f}'", .{ty.fmt(pt)}), else => return sema.fail(block, ty_src, "expected number, found '{f}'", .{ty.fmt(pt)}),
} }
@ -37176,7 +37176,14 @@ fn explainWhyValueContainsReferenceToComptimeVar(sema: *Sema, msg: *Zcu.ErrorMsg
} }
} }
fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc, val: Value, intermediate_value_count: u32, start_value_name: InternPool.NullTerminatedString) Allocator.Error!union(enum) { fn notePathToComptimeAllocPtr(
sema: *Sema,
msg: *Zcu.ErrorMsg,
src: LazySrcLoc,
val: Value,
intermediate_value_count: u32,
start_value_name: InternPool.NullTerminatedString,
) Allocator.Error!union(enum) {
done, done,
new_val: Value, new_val: Value,
} { } {
@ -37187,7 +37194,7 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,
var first_path: std.ArrayListUnmanaged(u8) = .empty; var first_path: std.ArrayListUnmanaged(u8) = .empty;
if (intermediate_value_count == 0) { if (intermediate_value_count == 0) {
try first_path.print(arena, "{fi}", .{start_value_name.fmt(ip)}); try first_path.print(arena, "{f}", .{start_value_name.fmt(ip)});
} else { } else {
try first_path.print(arena, "v{d}", .{intermediate_value_count - 1}); try first_path.print(arena, "v{d}", .{intermediate_value_count - 1});
} }
@ -37283,7 +37290,7 @@ fn notePathToComptimeAllocPtrInner(sema: *Sema, val: Value, path: *std.ArrayList
const backing_enum = union_ty.unionTagTypeHypothetical(zcu); const backing_enum = union_ty.unionTagTypeHypothetical(zcu);
const field_idx = backing_enum.enumTagFieldIndex(.fromInterned(un.tag), zcu).?; const field_idx = backing_enum.enumTagFieldIndex(.fromInterned(un.tag), zcu).?;
const field_name = backing_enum.enumFieldName(field_idx, zcu); const field_name = backing_enum.enumFieldName(field_idx, zcu);
try path.print(arena, ".{fi}", .{field_name.fmt(ip)}); try path.print(arena, ".{f}", .{field_name.fmt(ip)});
return sema.notePathToComptimeAllocPtrInner(.fromInterned(un.val), path); return sema.notePathToComptimeAllocPtrInner(.fromInterned(un.val), path);
}, },
.aggregate => |agg| { .aggregate => |agg| {
@ -37308,7 +37315,7 @@ fn notePathToComptimeAllocPtrInner(sema: *Sema, val: Value, path: *std.ArrayList
try path.print(arena, "[{d}]", .{elem_idx}); try path.print(arena, "[{d}]", .{elem_idx});
} else { } else {
const name = agg_ty.structFieldName(elem_idx, zcu).unwrap().?; const name = agg_ty.structFieldName(elem_idx, zcu).unwrap().?;
try path.print(arena, ".{fi}", .{name.fmt(ip)}); try path.print(arena, ".{f}", .{name.fmt(ip)});
}, },
else => unreachable, else => unreachable,
} }

View File

@ -723,7 +723,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
if (std.debug.runtime_safety) { if (std.debug.runtime_safety) {
if (self.air_bookkeeping < old_air_bookkeeping + 1) { if (self.air_bookkeeping < old_air_bookkeeping + 1) {
std.debug.panic("in codegen.zig, handling of AIR instruction %{d} ('{s}') did not do proper bookkeeping. Look for a missing call to finishAir.", .{ inst, air_tags[@intFromEnum(inst)] }); std.debug.panic("in codegen.zig, handling of AIR instruction %{d} ('{t}') did not do proper bookkeeping. Look for a missing call to finishAir.", .{ inst, air_tags[@intFromEnum(inst)] });
} }
} }
} }

View File

@ -2046,7 +2046,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
try cg.genInst(inst); try cg.genInst(inst);
if (std.debug.runtime_safety and cg.air_bookkeeping < old_bookkeeping_value + 1) { if (std.debug.runtime_safety and cg.air_bookkeeping < old_bookkeeping_value + 1) {
std.debug.panic("Missing call to `finishAir` in AIR instruction %{d} ('{s}')", .{ std.debug.panic("Missing call to `finishAir` in AIR instruction %{d} ('{t}')", .{
inst, inst,
cg.air.instructions.items(.tag)[@intFromEnum(inst)], cg.air.instructions.items(.tag)[@intFromEnum(inst)],
}); });
@ -3326,7 +3326,7 @@ fn emitUndefined(cg: *CodeGen, ty: Type) InnerError!WValue {
}, },
else => unreachable, else => unreachable,
}, },
else => return cg.fail("Wasm TODO: emitUndefined for type: {s}\n", .{ty.zigTypeTag(zcu)}), else => return cg.fail("Wasm TODO: emitUndefined for type: {t}\n", .{ty.zigTypeTag(zcu)}),
} }
} }

View File

@ -1680,7 +1680,7 @@ pub const DeclGen = struct {
try w.writeAll("{("); try w.writeAll("{(");
const ptr_ty = ty.slicePtrFieldType(zcu); const ptr_ty = ty.slicePtrFieldType(zcu);
try dg.renderType(w, ptr_ty); try dg.renderType(w, ptr_ty);
return w.print("){f}, {0fx}}}", .{ return w.print("){f}, {0f}}}", .{
try dg.fmtIntLiteralHex(.undef_usize, .Other), try dg.fmtIntLiteralHex(.undef_usize, .Other),
}); });
}, },

View File

@ -437,7 +437,7 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {
try argv.append(try allocPrint(arena, "-PDBALTPATH:{s}", .{out_pdb_basename})); try argv.append(try allocPrint(arena, "-PDBALTPATH:{s}", .{out_pdb_basename}));
} }
if (comp.version) |version| { if (comp.version) |version| {
try argv.append(try allocPrint(arena, "-VERSION:{f}.{f}", .{ version.major, version.minor })); try argv.append(try allocPrint(arena, "-VERSION:{d}.{d}", .{ version.major, version.minor }));
} }
if (target_util.llvmMachineAbi(target)) |mabi| { if (target_util.llvmMachineAbi(target)) |mabi| {

View File

@ -3336,8 +3336,8 @@ fn buildOutputType(
var hasher = file_writer.interface.hashed(Cache.Hasher.init("0123456789abcdef"), &buffer); var hasher = file_writer.interface.hashed(Cache.Hasher.init("0123456789abcdef"), &buffer);
var stdin_reader = fs.File.stdin().readerStreaming(&.{}); var stdin_reader = fs.File.stdin().readerStreaming(&.{});
_ = hasher.writer.sendFileAll(&stdin_reader, .unlimited) catch |err| switch (err) { _ = hasher.writer.sendFileAll(&stdin_reader, .unlimited) catch |err| switch (err) {
error.WriteFailed => fatal("failed to write {s}: {s}", .{ dump_path, file_writer.err.? }), error.WriteFailed => fatal("failed to write {s}: {t}", .{ dump_path, file_writer.err.? }),
else => fatal("failed to pipe stdin to {s}: {s}", .{ dump_path, err }), else => fatal("failed to pipe stdin to {s}: {t}", .{ dump_path, err }),
}; };
try hasher.writer.flush(); try hasher.writer.flush();

View File

@ -102,7 +102,7 @@ pub fn print(
.enum_tag => |enum_tag| { .enum_tag => |enum_tag| {
const enum_type = ip.loadEnumType(val.typeOf(zcu).toIntern()); const enum_type = ip.loadEnumType(val.typeOf(zcu).toIntern());
if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| { if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| {
return writer.print(".{fi}", .{enum_type.names.get(ip)[tag_index].fmt(ip)}); return writer.print(".{f}", .{enum_type.names.get(ip)[tag_index].fmt(ip)});
} }
if (level == 0) { if (level == 0) {
return writer.writeAll("@enumFromInt(...)"); return writer.writeAll("@enumFromInt(...)");
@ -207,7 +207,7 @@ fn printAggregate(
for (0..max_len) |i| { for (0..max_len) |i| {
if (i != 0) try writer.writeAll(", "); if (i != 0) try writer.writeAll(", ");
const field_name = ty.structFieldName(@intCast(i), zcu).unwrap().?; const field_name = ty.structFieldName(@intCast(i), zcu).unwrap().?;
try writer.print(".{fi} = ", .{field_name.fmt(ip)}); try writer.print(".{f} = ", .{field_name.fmt(ip)});
try print(try val.fieldValue(pt, i), writer, level - 1, pt, opt_sema); try print(try val.fieldValue(pt, i), writer, level - 1, pt, opt_sema);
} }
try writer.writeAll(" }"); try writer.writeAll(" }");
@ -392,14 +392,14 @@ pub fn printPtrDerivation(
const agg_ty = (try field.parent.ptrType(pt)).childType(zcu); const agg_ty = (try field.parent.ptrType(pt)).childType(zcu);
switch (agg_ty.zigTypeTag(zcu)) { switch (agg_ty.zigTypeTag(zcu)) {
.@"struct" => if (agg_ty.structFieldName(field.field_idx, zcu).unwrap()) |field_name| { .@"struct" => if (agg_ty.structFieldName(field.field_idx, zcu).unwrap()) |field_name| {
try writer.print(".{fi}", .{field_name.fmt(ip)}); try writer.print(".{f}", .{field_name.fmt(ip)});
} else { } else {
try writer.print("[{d}]", .{field.field_idx}); try writer.print("[{d}]", .{field.field_idx});
}, },
.@"union" => { .@"union" => {
const tag_ty = agg_ty.unionTagTypeHypothetical(zcu); const tag_ty = agg_ty.unionTagTypeHypothetical(zcu);
const field_name = tag_ty.enumFieldName(field.field_idx, zcu); const field_name = tag_ty.enumFieldName(field.field_idx, zcu);
try writer.print(".{fi}", .{field_name.fmt(ip)}); try writer.print(".{f}", .{field_name.fmt(ip)});
}, },
.pointer => switch (field.field_idx) { .pointer => switch (field.field_idx) {
Value.slice_ptr_index => try writer.writeAll(".ptr"), Value.slice_ptr_index => try writer.writeAll(".ptr"),

View File

@ -238,7 +238,7 @@ pub fn RegisterManager(
if (i < count) return null; if (i < count) return null;
for (regs, insts) |reg, inst| { for (regs, insts) |reg, inst| {
log.debug("tryAllocReg {} for inst {f}", .{ reg, inst }); log.debug("tryAllocReg {} for inst {?f}", .{ reg, inst });
self.markRegAllocated(reg); self.markRegAllocated(reg);
if (inst) |tracked_inst| { if (inst) |tracked_inst| {
@ -317,7 +317,7 @@ pub fn RegisterManager(
tracked_index: TrackedIndex, tracked_index: TrackedIndex,
inst: ?Air.Inst.Index, inst: ?Air.Inst.Index,
) AllocationError!void { ) AllocationError!void {
log.debug("getReg {} for inst {f}", .{ regAtTrackedIndex(tracked_index), inst }); log.debug("getReg {} for inst {?f}", .{ regAtTrackedIndex(tracked_index), inst });
if (!self.isRegIndexFree(tracked_index)) { if (!self.isRegIndexFree(tracked_index)) {
// Move the instruction that was previously there to a // Move the instruction that was previously there to a
// stack allocation. // stack allocation.
@ -349,7 +349,7 @@ pub fn RegisterManager(
tracked_index: TrackedIndex, tracked_index: TrackedIndex,
inst: ?Air.Inst.Index, inst: ?Air.Inst.Index,
) void { ) void {
log.debug("getRegAssumeFree {} for inst {f}", .{ regAtTrackedIndex(tracked_index), inst }); log.debug("getRegAssumeFree {} for inst {?f}", .{ regAtTrackedIndex(tracked_index), inst });
self.markRegIndexAllocated(tracked_index); self.markRegIndexAllocated(tracked_index);
assert(self.isRegIndexFree(tracked_index)); assert(self.isRegIndexFree(tracked_index));