Attributes in Rust are extra instructions or metadata that you attach to code elements like functions, structs, enums, or modules. They guide the compiler or tools on how to treat the code.
Syntax of attributes: Attributes start with # and are inside square brackets. For example:
#[attribute_name]
- It is useful for compiler behavior like enabling or disabling warnings, enforcing rules, or optimize certain code.
- Automatic derivations, for example #[derive(Debug)] automatically implements the Debug trait for a struct.
Types of Rust Attributes
Rust attributes can be divided into the following categories:
- Derive Attributes
- Testing Attributes
- Compiler Control Attributes
- Documentation Attributes
- Conditional Compilation Attributes
How to Use Attributes in Rust?
Attributes are written above the code they apply to. You can attach attributes to functions, structs, enums, modules, and even the entire crate.
1) Derive Attributes
In Rust, derive attributes are a special type of attribute that tell the compiler to automatically generate certain trait implementations for your struct or enum without writing them manually.
Example: Derive Debug Using #[derive(Debug, Clone)]
#[derive(Debug, Clone)]
struct Book {
title: String,
pages: u32,
}
fn main() {
// Create a Book instance
let original = Book {
title: String::from("Rust Made Easy"),
pages: 280,
};
// Because of `Clone`, we can duplicate it
let copy = original.clone();
// Because of `Debug`, we can print the struct directly
println!("Original: {:?}", original);
println!("Copied: {:?}", copy);
}
Explanation:
- [derive(Debug, Clone)]:
- Debug → It has been able to print the struct using println!(“{:?}”, …).
- Clone → This can create a copy of the struct with .clone().
Without derive, you have to manually write the impl Debug and imple Clone code.
2) Testing Attributes
In Rust, testing attributes are special compiler instructions that mark certain parts of your code as test-related. They tell the compiler that a function or module should only be compiled and executed during testing, not in the normal runtime of your program.
Example: Writing a Test Function
// This module will only compile during `cargo test`
#[cfg(test)]
mod tests {
// This function is a test case
#[test]
fn add_two_numbers() {
let result = 3 + 5;
assert_eq!(result, 8); // The test will pass because 3 + 5 = 8
}
// You can write multiple tests
#[test]
fn check_string_length() {
let name = String::from("Rust");
assert_eq!(name.len(), 4); // This will also pass
}
}
Explanation:
- #[test]: When you run cargo test, Rust automatically searches for all #[test] functions and runs them.
- #[cfg(test)]: It means “compile this block only when testing.”
Run tests using:
cargo test
3) Compiler Control Attributes
Compiler control attributes are special instructions that allow you to control how the Rust compiler checks, warns, or enforces certain rules in your code.
Example: Allow Unused Variables
#[allow(unused_variables)]
fn main() {
let x = 10; // Normally a warning, but now ignored
}
Explanation:
- #[allow(unused_variables)]: Tells the compiler to ignore warnings about unused variables.
Example: Deny Warnings
#[deny(warnings)] – Tells the compiler to treat all warnings as errors, forcing you to fix them before compiling. For example:
#[deny(warnings)]
fn main() {
let x = 10; // This now causes a compile-time error if unused
}
4) Documentation Attributes
Documentation attributes are special comments that help you write structured, readable, and automatically generated documentation for your code.
Example: Add Documentation
/// This function adds two numbers together and returns the result.
fn add(a: i32, b: i32) -> i32 {
a + b
}
Run this command to generate HTML documentation:
cargo doc --open
Explanation:
- ///: Marks a comment as documentation.
5) Conditional Compilation Attributes
Conditional compilation attributes allow us to control which parts of our code are compiled based on specific conditions, such as the operating system, build configuration, or custom features.
Example: Platform-Specific Code
#[cfg(target_os = "windows")]
fn print_os() {
println!("Running on Windows!");
}
#[cfg(target_os = "linux")]
fn print_os() {
println!("Running on Linux!");
}
fn main() {
print_os();
}
Explanation:
- #[cfg(target_os = “windows”)]: This function will only compile and run on Windows.
- #[cfg(target_os = “linux”)]: This version will only compile and run on Linux.
6) Crate-Level Attributes
Crate-level attributes are special instructions that apply to the entire project (crate) rather than just a single function, module, or struct.
Example: Define Crate Type
#![crate_type = "lib"]
#![crate_name = "my_crate"]
pub fn greet() {
println!("Hello from my_crate!");
}
Explanation:
- #![crate_type = “lib”]: Tells the compiler that this project should be built as a library instead of a binary executable.
- #![crate_name = “my_crate”]: Sets the name of the crate.
Learn Other Topics About Rust
- What are threads in Rust?
- What is concurrency in Rust?
- What is error handling in Rust?
- What is an HashMap in Rust?
- What is an Iterator in Rust?
- What is Mutex in Rust?
- What is Async in Rust?

M.Sc. (Information Technology). I explain AI, AGI, Programming and future technologies in simple language. Founder of BoxOfLearn.com.