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

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!");
    }
}

cfg-if

cfg-if cfg-if-crates.io cfg-if-github cfg-if-lib.rs

A macro to ergonomically define an item depending on a large number of #[cfg] parameters. Structured like an if-else chain, the first matching branch is the item that gets emitted.


// The `cfg-if` crate is useful for conditional compilation based on
// configuration flags.

// First, add the dependency to your Cargo.toml:
// [dependencies]
// cfg-if = "1.0.0"

use cfg_if::cfg_if;

fn main() {
    // Basic usage example
    cfg_if! {
        if #[cfg(target_os = "windows")] {
            println!("Running on Windows!");
        } else if #[cfg(target_os = "macos")] {
            println!("Running on macOS!");
        } else if #[cfg(target_os = "linux")] {
            println!("Running on Linux!");
        } else {
            println!("Running on an unknown platform!");
        }
    }

    // Another example with feature flags
    cfg_if! {
        if #[cfg(feature = "full")] {
            fn get_functionality() -> &'static str {
                "Full functionality enabled"
            }
        } else {
            fn get_functionality() -> &'static str {
                "Limited functionality only"
            }
        }
    }

    println!("Functionality: {}", get_functionality());

    // Nested example
    cfg_if! {
        if #[cfg(target_arch = "x86_64")] {
            cfg_if! {
                if #[cfg(target_feature = "avx2")] {
                    println!("Using AVX2 optimized routines");
                } else if #[cfg(target_feature = "sse2")] {
                    println!("Using SSE2 optimized routines");
                } else {
                    println!("Using standard routines");
                }
            }
        } else {
            println!("Architecture-specific optimizations not available");
        }
    }
}

Related Topics

  • Derive.
  • Rust Patterns.
  • Testing.

References