Attributes and Conditional Compilation

What Are Attributes

An attribute is a structured metadata annotation—written #[...] (outer attribute) or #![...] (inner attribute)—attached to a crate, module, item, statement, or expression to instruct the compiler, linker, documentation generator (rustdoc), or procedural macros how to process that code.

Syntactic Forms of Attributes

Every attribute encloses a meta-item inside #[(...)] or #![(...)]. Rust supports three meta-item grammars:

Meta-Item Form Syntax Examples
Plain path #[path::to::attr] #[test], #[inline], #[must_use], #[non_exhaustive]
Key-value pair #[path = literal_or_expr] #[doc = "Summary"], #[path = "unix_imp.rs"], #[must_use = "reason"]
Token-tree argument list #[path(args...)] #[derive(Debug, Clone)], #[cfg(target_os = "macos")], #[repr(C, align(8))]
Anatomy of an Attribute:

  #[cfg_attr(target_os = "linux", allow(dead_code))]
  ^^~~~~~~~~ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^
  | |        |                                      +-- Closing bracket
  | |        +-- Attribute input (token tree / arguments)
  | +-- Attribute path (`cfg_attr`)
  +-- Outer attribute sigil (`#[` vs inner `#![`)

The Four Sources of Attributes in Rust

Attribute Source Examples Processed By
1. Built-in compiler attributes #[cfg], #[repr], #[inline], #[must_use], #[allow] rustc directly
2. Standard macro / test attributes #[derive(...)], #[test], #[bench] Built-in macro expander & test harness
3. Tool attributes (tool::attr) #[rustfmt::skip], #[clippy::cognitive_complexity], #[rust_analyzer::...] External tools (rustfmt, clippy, IDEs)
4. Procedural macro attributes #[tokio::main], #[serde(rename_all = "camelCase")] Custom proc-macro crates at compile time

Unsafe Attributes in Rust 2024 Edition (#[unsafe(...)])

Starting in the Rust 2024 edition, attributes that carry memory-safety or linker-soundness preconditions—specifically no_mangle, export_name, and link_section—must be wrapped in #[unsafe(...)] to make their safety contract explicit:

// In Rust 2024 edition, `no_mangle` and `export_name` require `#[unsafe(...)]`:
#[unsafe(no_mangle)]
pub extern "C" fn rust_add(a: i32, b: i32) -> i32 {
    a + b
}

#[derive(Debug, PartialEq)]
#[must_use = "PointResult must be inspected"]
struct PointResult {
    x: i32,
    y: i32,
}

fn main() {
    let sum = rust_add(15, 27);
    let pt = PointResult { x: sum, y: 0 };
    println!("pt = {:?}", pt);
}
pt = PointResult { x: 42, y: 0 }