Check format strings at compile time in the mh::format family#23
Open
pr-minder[bot] wants to merge 2 commits into
Open
Check format strings at compile time in the mh::format family#23pr-minder[bot] wants to merge 2 commits into
pr-minder[bot] wants to merge 2 commits into
Conversation
mh::format, mh::format_to, mh::format_to_container, and mh::format_to_n now take a typed, backend-checked format string parameter (narrow and wide overloads) instead of laundering every string through the backend's runtime() escape. Literal format strings are validated against the argument types at compile time; a format string only known at runtime must be explicitly wrapped in the new mh::runtime escape hatch: mh::format(mh::runtime(str), args...). vformat, try_format, and try_vformat keep their runtime-checked contracts, with try_format rerouted through mh::runtime internally. Call sites that assemble format strings at runtime (the source_location and enum_fmt formatters, base_format_string::fmt, and the format_string constructor SFINAE) now wrap them in mh::runtime, and the runtime-format-string test is updated to document the new contract. The wide format_to/format_to_n overloads delegate through the backend's vformat* layer because the shape of the typed wide overloads varies across supported fmt versions; the compile-time check already happened while constructing the wformat_string_t parameter. Under the (disabled) STL backend the typed aliases map to std::format_string, fixing a latent reference to the nonexistent std runtime(). Co-Authored-By: Claude <noreply@anthropic.com>
…trings Configure-time try_compile gate (fmt backend only): a format string referencing a missing argument must fail to compile, with a valid-string positive control so a broken harness cannot fake a pass. try_compile ignores non-imported targets in LINK_LIBRARIES, so the TUs use the include directory directly plus the imported fmt::fmt target. Also add runtime tests that the typed, mh::runtime, and vformat paths agree, and update the README for compile-time checking (under MH_FORMATTER_NONE the format family is absent, not a built-in fallback). Co-Authored-By: Claude <noreply@anthropic.com>
PazerOP
marked this pull request as draft
July 21, 2026 20:02
PazerOP
marked this pull request as ready for review
July 21, 2026 20:15
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Before: an invalid format string passed to
mh::formatand friends compiled fine and threwmh::format_errorat runtime. After: it fails the build. A format string only known at runtime opts in explicitly by wrapping it inmh::runtime()— or by usingmh::vformat/mh::try_format, which remain runtime-checked by design.How:
mh::format/format_to/format_to_container/format_to_nnow take a typed format-string parameter per backend (fmt::format_stringunder fmtlib,std::format_stringunder the STL backend) whose consteval constructor checks literal format strings against the argument types;MH_FORMATTER_NONEbuilds are unaffected. Call sites that assemble format strings at runtime (thesource_locationand enum formatters,mh::fmtstr) now wrap them inmh::runtime(). A CMake configure-time negative-compile check asserts that a format string referencing a missing argument fails to build, with a valid-string positive control so a broken harness cannot fake a pass; it runs only when the fmt backend is active.