Attributes and Conditional Compilation

#[cfg(...)]

#[cfg(predicate)] is the primary conditional compilation attribute in Rust. During AST expansion, the compiler evaluates predicate:

  • If predicate is true, the annotated item, module, struct field, enum variant, match arm, or statement is kept and compiled normally.
  • If predicate is false, 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!