std.fmt: fix unecessary deref on user-defined format function

When formatting a pointer to user type, currently it needs to be
dereferenced first, then call `formatType` on the child type.

Fix the problem by checking for "format" function on not only the type
itself, but also the struct it points to. Add hasMethod to std.meta.
This commit is contained in:
Khang Nguyen Duy 2023-07-09 22:18:52 +07:00 committed by Andrew Kelley
parent aef1da1634
commit 993a83081a
2 changed files with 10 additions and 1 deletions

View File

@ -489,7 +489,7 @@ pub fn formatType(
return formatAddress(value, options, writer);
}
if (std.meta.hasFn(T, "format")) {
if (std.meta.hasMethod(T, "format")) {
return try value.format(actual_fmt, options, writer);
}

View File

@ -1129,6 +1129,15 @@ pub inline fn hasFn(comptime T: type, comptime name: []const u8) bool {
return @typeInfo(@TypeOf(@field(T, name))) == .Fn;
}
/// Returns true if a type has a `name` method; `false` otherwise.
/// Result is always comptime-known.
pub inline fn hasMethod(comptime T: type, comptime name: []const u8) bool {
return switch (@typeInfo(T)) {
.Pointer => |P| hasFn(P.child, name),
else => hasFn(T, name),
};
}
/// True if every value of the type `T` has a unique bit pattern representing it.
/// In other words, `T` has no unused bits and no padding.
/// Result is always comptime-known.