From 993a83081a975464d1201597cf6f4cb7f6735284 Mon Sep 17 00:00:00 2001 From: Khang Nguyen Duy <40488299+iceghost@users.noreply.github.com> Date: Sun, 9 Jul 2023 22:18:52 +0700 Subject: [PATCH] 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. --- lib/std/fmt.zig | 2 +- lib/std/meta.zig | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index a9e1d73c0..f89a20506 100644 --- a/lib/std/fmt.zig +++ b/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); } diff --git a/lib/std/meta.zig b/lib/std/meta.zig index 94d5f962b..f77ed6d34 100644 --- a/lib/std/meta.zig +++ b/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.