concat!
The concat! macro concatenates a comma-separated sequence of compile-time literals (strings, characters, integers, floats, and booleans) into a single &'static str literal at compile time with zero runtime overhead.
Supported Literal Types
Unlike string concatenation with + or format!, which runs at runtime and allocates a String on the heap, concat! runs entirely during macro expansion and produces a static string literal "...":
const BANNER: &str = concat!("app-v", 2, '.', 4, "-tls=", true);
fn main() {
println!("Compile-time banner: {BANNER}");
}
Compile-time banner: app-v2.4-tls=true
Note that concat! accepts only literal tokens (or macros that expand directly into literal tokens, such as env!, file!, line!, column!, module_path!, and stringify!). Passing a const variable identifier (const VERSION: &str = "1.0"; concat!(VERSION, "!")) fails because VERSION is an identifier token rather than a literal token.
Composing Macro-Generated Strings (env!, file!, line!, stringify!)
Because built-in compiler macros like env!("CARGO_PKG_VERSION"), file!(), line!(), and stringify!(...) expand to literal tokens, concat! can join them at compile time inside const declarations, doc attributes (#[doc = concat!(...)]), or compile_error! messages:
const BUILD_TAG: &str = concat!(
"source=",
file!(),
":",
line!(),
" (",
stringify!(release_profile),
")"
);
fn main() {
println!("{BUILD_TAG}");
}
source=src/main.rs:1: (release_profile)
concat! vs. format!
| Aspect | concat!("a", 1, true) |
format!("a{}{}", 1, true) |
|---|---|---|
| When it runs | Compile time (macro expansion) | Runtime |
| Return type | &'static str (0 heap allocations) |
String (heap-allocated) |
Usable in const / static / #[doc = ...]? |
Yes | No |
Accepts runtime variables or const identifiers? |
No (literals and literal-producing macros only) | Yes |