From 08a0cf096bb32cea1e87e74e5484b2dfb6fd3ebb Mon Sep 17 00:00:00 2001 From: Kefu Chai Date: Fri, 31 Jul 2026 11:01:41 +0800 Subject: [PATCH] crimson/os/seastore/onode_manager: opt staged_position_t out of fmt range formatting staged_position_t has static begin()/end() factory methods, unrelated to iteration, that each return another staged_position_t. fmt's range auto-detection picks up any type with .begin()/.end() members and treats it as a range, then dereferences whatever begin() returns to work out the element type. staged_position_t has no operator*, so seastar's compile-time format-string check fails wherever it's logged alongside other arguments: /usr/include/fmt/ranges.h:283:14: error: no match for 'operator*' (operand type is 'staged_position_t<2>::me_t') 283 | decltype(*detail::range_begin(std::declval())); Reproduced with fmt 10.1.1 (Debian's libfmt-dev 10.1.1+ds1-4). Specialize fmt::is_range to false for staged_position_t to opt out, the same idea seastar's own sstring already applies to its fmt::range_format_kind for the same reason (src/seastar/include/seastar/core/sstring.hh). Ceph's WITH_SYSTEM_FMT accepts fmt 8.1.1 through 11.1.4 (src/CMakeLists.txt:429); range_format_kind only exists from fmt 9.1.0 onward, while is_range keeps the same specializable signature across that whole range, so this needs no version guard. is_range is declared in fmt/ranges.h, which common/fmt_common.h deliberately doesn't include, so pull it in directly here rather than relying on some other header to have done so first. Signed-off-by: Kefu Chai --- .../onode_manager/staged-fltree/stages/stage_types.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/crimson/os/seastore/onode_manager/staged-fltree/stages/stage_types.h b/src/crimson/os/seastore/onode_manager/staged-fltree/stages/stage_types.h index 815deea5d2e..d5793580ed0 100644 --- a/src/crimson/os/seastore/onode_manager/staged-fltree/stages/stage_types.h +++ b/src/crimson/os/seastore/onode_manager/staged-fltree/stages/stage_types.h @@ -8,6 +8,7 @@ #include #include "common/fmt_common.h" +#include #include "crimson/os/seastore/onode_manager/staged-fltree/fwd.h" #include "crimson/os/seastore/onode_manager/staged-fltree/node_types.h" #include "crimson/os/seastore/onode_manager/staged-fltree/value.h" @@ -444,6 +445,13 @@ std::ostream& operator<<( namespace fmt { +// staged_position_t has static begin()/end() factory methods unrelated to +// iteration; fmt's range auto-detection picks them up and tries to +// dereference the (non-dereferenceable) result, so opt out explicitly. +template +struct is_range, char> + : std::false_type {}; + template struct formatter> { constexpr auto parse(fmt::format_parse_context& ctx) { return ctx.begin(); }