Attributes and Conditional Compilation
#[cfg(...)]
#[cfg(predicate)] is the primary conditional compilation attribute in Rust. During AST expansion, the compiler evaluates predicate:
- If
predicateistrue, the annotated item, module, struct field, enum variant, match arm, or statement is kept and compiled normally. - If
predicateisfalse, the annotated node is completely stripped from the Abstract Syntax Tree (AST) before name resolution, type checking, or borrow checking even run.
Source Code with `#[cfg(...)]`:
#[cfg(target_os = "windows")]
fn platform_name() -> &'static str { "Windows" }
#[cfg(not(target_os = "windows"))]
fn platform_name() -> &'static str { "Unix / Other" }
AST Seen by Type Checker on macOS / Linux:
fn platform_name() -> &'static str { "Unix / Other" }
(The Windows function is completely removed from the AST!)
Boolean Combinators Inside #[cfg(...)]
Configuration predicates can be composed arbitrarily using three boolean operators:
| Combinator | Syntax | Evaluates to true When |
|---|---|---|
all(...) (Logical AND) |
#[cfg(all(unix, target_pointer_width = "64"))] |
Every sub-predicate inside all(...) is true |
any(...) (Logical OR) |
#[cfg(any(target_os = "linux", target_os = "macos"))] |
At least one sub-predicate inside any(...) is true |
not(...) (Logical NOT) |
#[cfg(not(debug_assertions))] |
The inner sub-predicate is false |
true / false literals (Rust 1.88+) |
#[cfg(false)] |
Unconditionally enabled (true) or disabled (false) |
Common Built-In Configuration Predicates
| Predicate Category | Examples | Set By |
|---|---|---|
| Target OS / Family | unix, windows, target_os = "linux", target_os = "macos" |
Target triple |
| CPU Architecture | target_arch = "x86_64", target_arch = "aarch64", target_endian = "little" |
Target triple |
| Build Profile / Assertions | debug_assertions (enabled in dev/test builds, disabled in --release by default) |
Profile settings |
| Test Harness | test (enabled only during cargo test / rustc --test) |
--test flag |
| Cargo Feature Flags | feature = "serde", feature = "tls" |
Cargo.toml [features] |
| Panic Strategy | panic = "unwind", panic = "abort" |
Profile panic setting |
Using #[cfg(...)] on Items, Struct Fields, and Match Arms
struct Diagnostics {
pub requests: u64,
// Field exists ONLY when `debug_assertions` is enabled:
#[cfg(debug_assertions)]
pub debug_trace: Vec<&'static str>,
}
impl Diagnostics {
fn new() -> Self {
Self {
requests: 0,
#[cfg(debug_assertions)]
debug_trace: Vec::new(),
}
}
fn record(&mut self, endpoint: &'static str) {
self.requests += 1;
#[cfg(debug_assertions)]
self.debug_trace.push(endpoint);
#[cfg(not(debug_assertions))]
let _ = endpoint;
}
}
fn main() {
let mut diag = Diagnostics::new();
diag.record("/api/v1/status");
println!("requests recorded: {}", diag.requests);
}
requests recorded: 1
Compile-Time Checked #[cfg] Names (Rust 1.80+ check-cfg)
Starting in Rust 1.80, Cargo and rustc automatically validate every #[cfg(...)] name and value against known built-in target values and the features declared in Cargo.toml (#[warn(unexpected_cfgs)]). If you misspell #[cfg(target_os = "macOS")] (instead of "macos") or reference an undeclared feature #[cfg(feature = "srede")], the compiler immediately warns you of the typo!