Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

An Overview of Attributes

Goal of This Episode

Survey Rust’s common attributes and understand the difference between outer and inner ones.

Concept

outer vs inner

  • outer attribute #[...]: goes above an item and decorates that item.
  • inner attribute #![...]: goes inside an item (usually at the top of a file) and decorates the enclosing item as a whole.
#![allow(dead_code)] // inner: applies to the whole mod

#[derive(Debug)]     // outer: applies to the struct below
struct Point { x: i32, y: i32 }

fn main() {}

The difference is one exclamation mark !.

derive

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct Color(u8, u8, u8);

fn main() {}

Warning Control

#[allow(dead_code)]        // don't warn about unused code
#[allow(unused_variables)] // don't warn about unused variables
#[warn(missing_docs)]      // turn on the "missing docs" warning
#[deny(unsafe_code)]       // upgrade "uses unsafe" to an error

Conditional Compilation

#[cfg(target_os = "windows")]
fn windows_only() { /* ... */ }

#[cfg(test)]
mod tests { /* ... */ }

Testing

#[test]
fn test_add() { assert_eq!(1 + 1, 2); }

#[test]
#[should_panic]
fn test_panic() { panic!("on purpose"); }

#[test]
#[ignore]
fn slow_test() { /* skip for now */ }

fn main() {}

Performance Hints

When a function is called, the program has to jump to the function’s location, run it, then jump back. inline is an optimization: the compiler “pastes” the function’s code directly into the call site, saving the jumping around.

#[inline]         // suggest the compiler inline this function
#[inline(always)] // suggest always inlining
#[inline(never)]  // suggest never inlining

Most of the time you don’t need to write these by hand — the compiler decides on its own. They’re only needed for small functions called across crates, or in performance-critical spots.

Memory Layout

Rust’s compiler freely rearranges a struct’s fields in memory and adjusts alignment to save space. But if you’re interoperating with C, C structs have fixed layout rules — #[repr(C)] tells Rust “lay this out by C’s rules”:

#[repr(C)]  // use C's memory layout
#[repr(u8)] // enum underlying type (from last episode)

Other Common Ones

#[must_use] on a function or type makes the compiler warn if a caller receives the return value but doesn’t use it. Result carries #[must_use] — that’s why you see a warning when you don’t handle a Result.

#[must_use]
fn compute() -> i32 { 42 }

fn main() {
    compute(); // warning: unused return value
    let _ = compute(); // OK: explicitly ignore with let _
}
#[non_exhaustive] // tell other crates this enum / struct may gain new items later
#[deprecated]     // mark as deprecated
#[deprecated(since = "2.0", note = "use new_function instead")]

Doc Comments Are Attribute Shorthand

/// This is a function
fn foo() {}

// is the same as
#[doc = "This is a function"]
fn foo() {}

/// is just shorthand for #[doc = "..."]. Likewise, //! is shorthand for #![doc = "..."] — used at the top of a file to document a whole mod or crate.

Example Code

#![allow(dead_code)]

#[derive(Debug, Clone, PartialEq)]
struct Config {
    name: String,
    value: i32,
}

#[must_use]
fn create_config(name: &str, value: i32) -> Config {
    Config { name: String::from(name), value }
}

#[deprecated(note = "use create_config instead")]
fn make_config() -> Config {
    create_config("default", 0)
}

#[cfg(target_os = "linux")]
fn linux_only() {
    println!("only runs on Linux");
}

fn main() {
    let c = create_config("test", 42);
    println!("{:?}", c);
}

Recap

  • #[...] (outer) decorates the item below it; #![...] (inner) decorates the item containing it.
  • #[derive(...)]: auto-implement traits.
  • #[allow/warn/deny(...)]: control warnings.
  • #[cfg(...)]: conditional compilation.
  • #[test] / #[should_panic] / #[ignore]: test-related
  • #[must_use]: warn when the return value is ignored.
  • #[deprecated]: mark as deprecated.
  • /// is shorthand for #[doc = "..."]; //! is shorthand for #![doc = "..."].