concat! / stringify! / line! / column! / file! / module_path!Macro
Explanation
Six small macros, each producing a compile-time value from source text or build position rather than from any runtime computation:
concat!(a, b, ...)concatenates literal arguments (string, char, numeric, boolean literals) into a single string literal, entirely at compile time — it cannot take arbitrary runtime expressions the wayformat!can; every argument must itself be a literal.stringify!(tokens)turns a sequence of tokens back into a string containing their own source text, without evaluating or type-checking them as an expression —stringify!(1 + 1)produces the string"1 + 1", not"2". This is exactly what powersassert!'s default failure message (seeassert!/assert_eq!/assert_ne!): the condition passed toassert!is captured withstringify!so the panic message can show the reader the literal source of the check that failed.line!(),column!(), andfile!()each expand to a compile-time constant giving the current source location — the line number, column number, and file path of the macro invocation itself, respectively.module_path!()expands to a string literal of the current module's dotted path (e.g."myapp::handlers::orders"), as seen from the crate root.
All six are commonly composed together inside other macros to build
informative diagnostic or log messages that name their own call site —
line!()/file!()/module_path!() give the "where," stringify! gives
the "what," concat! joins the pieces into one literal. For call-site
information tied to a specific function rather than the macro
invocation itself, #[track_caller]
plus std::panic::Location::caller() is the runtime equivalent used by
unwrap() and similar methods to report where they were called from.
Usage examples
Capturing source text and concatenating literals
let expr_text = stringify!(1 + 2); // <- "1 + 2", the source text, not the evaluated "3"
let banner = concat!("build ", "v", "1.0.3"); // <- joined into one &'static str at compile time
Testing
A small custom assertion macro reports the failed condition's own source
text using stringify!, the same technique the standard assert! macro
uses internally.
macro_rules! check_positive {
($value:expr) => {
if $value <= 0 {
panic!(
"expected {} to be positive, got {}",
stringify!($value), // <- turns the *expression itself* into a string, e.g. "order.total"
$value
);
}
};
}
struct Order { total: i64 }
let order = Order { total: -5 };
check_positive!(order.total); // panics: "expected order.total to be positive, got -5"
Reporting the expression's own source text
("order.total") rather than a hand-written label keeps the message
accurate automatically as the macro is reused at different call sites —
the same trick the
std docs describe
assert! itself as relying on for its default panic message.
Designing a public API
A lightweight logging macro tags every log line with its own source
location, using file!()/line!()/module_path!() rather than
requiring the caller to pass that information manually.
macro_rules! log_here {
($message:expr) => {
println!(
"[{}:{} ({})] {}",
file!(), line!(), module_path!(), $message
// <- all three are compile-time constants naming the call site of THIS invocation
)
};
}
fn process_order(order_id: u64) {
log_here!(format!("processing order {order_id}"));
}
Baking the call site into the macro itself means every
call site gets accurate location info for free without the caller having
to supply it — the same underlying technique logging crates in the
ecosystem build their own logging macros on top of, per the
std docs for
file!/line!/module_path!.