Commit 993a83081a

Khang Nguyen Duy <40488299+iceghost@users.noreply.github.com>
2023-07-09 17:18:52
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.
1 parent aef1da1
Changed files (2)
lib/std/fmt.zig
@@ -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);
     }
 
lib/std/meta.zig
@@ -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.