Attributes

Attributes

Attributes can take arguments with different syntaxes:

#[attribute = "value"]
#[attribute(key = "value")]
#[attribute(value)]
#[attribute(value, value2)]

Inner attributes #![attr] apply to the item that the attribute is declared within.

Lint attributes

During early development, place the following attributes at the top of main.rs or lib.rs

#![allow(unused_variables)]
#![allow(unused_mut)]
#![allow(unused_imports)]
#![allow(unused_must_use)]
// or simply: #![allow(unused)]
#![allow(dead_code)]
#![allow(missing_docs)]

// This import is not used anywhere
use std::thread;

// This struct is public but is not documented
pub struct S;

#[must_use]
fn required() -> u32 {
    42
}

// Nothing calls this function
fn dead_code() {}

fn main() {
    // This variable is not used
    let x = 1;
    // This mutable variable is not used
    let mut m = 2;
    // The return value of this function is not used
    required();
    println!("Done!");
}

For production-ready code, replace the above by the following, for example.

//! Crate documentation goes here.
#![warn(unused, missing_debug_implementations, missing_docs, rust_2018_idioms)]
// You may also add `missing_copy_implementations` if desirable.
// It detects potentially-forgotten implementations of Copy for public types.

// `deny` creates an error in case of violation
#![deny(unreachable_pub)]
// Prohibit unsafe blocks / functions
// `forbid` is the same as `deny`, but also forbids changing the lint level
// afterwards
#![forbid(unsafe_code)]

// WARNING: fn dead_code() {}

// ERROR: unsafe fn unsafe_func() {}

// ERROR
// fn unsafe_block() {
//     unsafe {
//     }
// }

/// This is the required documentation for S
/// We had to derive Debug to avoid a warning
#[derive(Debug)]
pub(crate) struct S;

/// Here is the required documentation
/// for the main function.
fn main() {
    let s = S;
    println!("{:?}", s);
}

You also apply these attributes to specific functions:

// Disables the `dead_code` lint
#[allow(dead_code)]
fn unused_function() {}

fn main() {
    println!("Nobody is calling `unused_function`.");
}

List of lint checks: rustc -W help. rustc⮳ also recognizes the tool lints for "clippy" and "rustdoc" e.g. #![warn(clippy::pedantic)]

Automatically derive common traits

See Automatic derivation.

Mark as must use

// Must use the results of the fn
// Also applies to traits, structs, enums...
#[must_use]
fn add(a: i32, b: i32) -> i32 {
    a + b
}

fn main() {
    println!("{}", add(1, 2));
}

Mark as deprecated

#![allow(deprecated)]

// Mark a function as deprecated
// That also works for structs, enums, etc...
#[deprecated(since = "5.2.0", note = "Use bar instead")]
pub fn foo() {
    println!("foo");
}

fn main() {
    // Use of a deprecated item
    foo();
    // Normally we would get a warning.
    // In this case, we used the module-wide #![allow(deprecated)] attribute
    // (first line above) to suppress it.
}

Compile conditionally

Conditional compilation

// This function only gets compiled if the target OS is linux
#[cfg(target_os = "linux")]
fn are_you_on_linux() {
    println!("You are running Linux!");
}

// And this function only gets compiled if the target OS is *not*
// linux
#[cfg(not(target_os = "linux"))]
fn are_you_on_linux() {
    println!("You are *not* running Linux!");
}

fn main() {
    are_you_on_linux();

    println!("Are you sure?");
    if cfg!(target_os = "linux") {
        // alternative: use cfg!
        println!("Yes. It's definitely Linux!");
    } else {
        println!("Yes. It's definitely *not* Linux!");
    }
}

See also

Attributes reference

Rust by example - attributes