compile_error!
The compile_error! macro unconditionally fails compilation with a custom error message whenever the macro call remains in the AST after macro expansion and #[cfg(...)] stripping.
Syntax
compile_error!("message explaining why compilation cannot proceed");
The single argument to compile_error! must be a string literal (or a macro that expands directly into a string literal, such as concat!("invalid token: ", stringify!($tok))).
Two Primary Use Cases for compile_error!
1. Enforcing Mutually Exclusive Cargo Features or Platform Constraints
Combined with #[cfg(...)], compile_error! fails the build immediately with a clear explanation if a user enables incompatible Cargo features or compiles for an unsupported target platform:
// Fails compilation only if BOTH `backend_sqlite` and `backend_postgres` features are enabled:
#[cfg(all(feature = "backend_sqlite", feature = "backend_postgres"))]
compile_error!(
"features `backend_sqlite` and `backend_postgres` are mutually exclusive; enable only one"
);
// Fails compilation on 16-bit targets:
#[cfg(target_pointer_width = "16")]
compile_error!("this crate requires at least a 32-bit pointer width");
fn main() {
println!("Configuration validated at compile time.");
}
Configuration validated at compile time.
(Note: When gating compile_error! on configuration flags, always use the #[cfg(...)] attribute rather than if cfg!(...) { compile_error!(...); }. Because if cfg!(...) does not strip its body from the AST, compile_error! inside an if false block will still fire and fail compilation!)
2. Custom Error Reporting in Declarative and Procedural Macros
When a user passes invalid syntax or unsupported options to a macro, expanding to compile_error! produces a clean, single-line diagnostic instead of exposing internal macro implementation details:
// ❌ does not compile
macro_rules! http_method {
(GET) => { "GET" };
(POST) => { "POST" };
($invalid:ident) => {
compile_error!(concat!(
"invalid HTTP method `",
stringify!($invalid),
"`; only `GET` and `POST` are supported"
))
};
}
fn main() {
let _m = http_method!(DELETE);
}
error: invalid HTTP method `DELETE`; only `GET` and `POST` are supported
--> src/main.rs:6:9
|
6 | / compile_error!(concat!(
7 | | "invalid HTTP method `",
8 | | stringify!($invalid),
9 | | "`; only `GET` and `POST` are supported"
10 | | ))
| |__________^
...
15 | let _m = http_method!(DELETE);
| -------------------- in this macro invocation