Common Standard Macros

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