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 }