Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

treewide: use fmtlib's fmt::format_string in format() #1727

Merged
merged 3 commits into from
Sep 3, 2024

Conversation

tchaikov
Copy link
Contributor

@tchaikov tchaikov commented Jul 8, 2023

this series enables seastar::format() to use compile-time format check.

using fmt::format_string would allow us to perform compile-time
format checking. so in this change, we switch to fmt::format_string
when fmtlib's version is greater or equal to 8.0, which introduced
the compile-time checking.

also, because the fmt::format_string can only be instantiated with
a compile-time constexpr, the fmt string specified in test is changed
to a constexpr accordingly.

please note, this is a breaking change which might require caller to use
seastar::format() if the tree is compiled with libstdc++ 13 or a standard
library with std::formt() implemented.

@tchaikov
Copy link
Contributor Author

tchaikov commented Jul 8, 2023

i am still working on getting scylladb compiled with this change.

now scylla compiles with the change. but still, this change is a breaking change.

@tchaikov
Copy link
Contributor Author

tchaikov commented Jul 9, 2023

i am still working on getting scylladb compiled with this change.

i think i hit a bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110602

EDIT, this is how ADL works. in other words, if the argument(s) are in the "std" namespace, std::format() is favored even if we have using seastar::format; and necessary forward declarations in seastarx.hh .

/home/kefu/dev/scylladb/utils/big_decimal.cc:52:37: error: call to 'format' is ambiguous
   52 |             throw marshal_exception(format("big_decimal - incorrect empty exponent: {}", text));
      |                                     ^~~~~~
/home/kefu/dev/scylladb/seastarx.hh:27:1: note: candidate function [with A = <std::basic_string_view<char> &>]
   27 | format(fmt::format_string<A...> fmt, A&&... a);
      | ^
/usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13/format:3713:5: note: candidate function [with _Args = <std::basic_string_view<char> &>]
 3713 |     format(format_string<_Args...> __fmt, _Args&&... __args)
      |     ^

so we would have to explicitly call seastar::format() if we want to use it.

this change replace all `format()` with `seastar::format()`.

this was not necessary if we don't change the function signature of
`seastar::format()`, even if we compile the tree with libstdc++
shipped with GCC-13, which implements `std::format()`. because
`std::format()` accepts a templated parameter of `fmt`, so the
`seastar::fmt()` which accepts a plain `const char*` always win
if we just call `format()` in the opened namespace of `seastar`.

but since we plan to change `seastar::format()` from
`format(const char* fmt, A&&... a)` to
`format(fmt::format_string<A...> fmt, A&&... a)`, we cannot
gurantee that `seastar::format()` will win in the function
resolution in the use case above. so we have to change all
call sites of this function to `seastar::format()` to disambiguate
it.

Signed-off-by: Kefu Chai <[email protected]>
because rpc logger needs to talk to both seastar::logger
and the user customized logger. the former does not accept
`fmt::format_string` yet, while the latter needs to accept
`seastar::format()`ed sstring. and we plan to change `seastar::format()`
to use compile-time format check. so to cater the needs of
both branches. we just decouple rpc logger from `seastar::format()`.
and let rpc logger to use `fmt::format_to()` directly.

this would allow us to change `seastar::format()`.

Signed-off-by: Kefu Chai <[email protected]>
using `fmt::format_string` would allow us to perform compile-time
format checking. so in this change, we switch to `fmt::format_string`
when fmtlib's version is greater or equal to 8.0, which introduced
the compile-time checking.

also, because the `fmt::format_string` can only be instantiated with
a compile-time constexpr, the fmt string specified in test is changed
to a constexpr accordingly.

Signed-off-by: Kefu Chai <[email protected]>
@tchaikov
Copy link
Contributor Author

tchaikov commented Sep 3, 2024

@scylladb/seastar-maint hello maintainers, could you help review this change?

if we have concerns on the backward compatibility like we did in 228bf07, i will add a macro which plays a similar role of SEASTAR_LOGGER_COMPILE_TIME_FMT, so that the existing Seastar application can opt out of this compile-time formatter. as, because the way how ADT works, applications will have to explicitly call either std::format() or seastar::format(). see also #1727 (comment)

@avikivity
Copy link
Member

Most reasonable applications don't use using namespace seastar.

@@ -140,9 +140,9 @@ log(A&&... a) {
*/
template <typename... A>
sstring
format(const char* fmt, A&&... a) {
format(fmt::format_string<A...> fmt, A&&... a) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need another overload for fmt::runtime, or will this work out of the box?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, runtime_format_string is convertible to basic_format_string.

@avikivity avikivity merged commit e3249a8 into scylladb:master Sep 3, 2024
14 checks passed
@tchaikov tchaikov deleted the std-format branch September 9, 2024 13:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants