But that's impractical, so the next soonest time is at startup.
A counter- and/or example of this is what Service Weaver does to try to bomb builds when generated files are older than their dependencies.
Remember C++ actually implements checks at compile time for the modern std::format function. That is, if you mess up the text of a format string so that it's invalid, C++ gives you a compile time error saying nope, that's not a valid format.
You might think that's just compiler magic, as it is for say printf-style formats in C, but nope, works for custom formats too, it's (extremely hairy) compile time executed C++.
Template type strings with inference would also allow you to parse the strings in the type system.
I cannot imagine wanting to build my routes table implicitly through import graph rather than having a specific place to aggregate.
For example, Phoenix Verified Routes in Elixir: https://hexdocs.pm/phoenix/Phoenix.VerifiedRoutes.html
I'd imagine something like this should be possible as well, but I'm not sure it would be worth it, considering the effort it would take to implement.
[1]: https://twitter.com/anuraghazru/status/1511776290487279616
Rust can very likely do it by leveraging their `build.rs` stuff to parse and validate call sites of the registration and parameters.
Zig can probably do it with their comptime stuff.
In theory, Go could do the same (but that would mean special-casing the `net/http` handler registration in the compiler). At least `go vet` is smart enough to yell at you about wrong format string arguments.