Rust Attributes Basics
An attribute is an instruction for the compiler, written above the code it applies to. It sits inside square brackets with a #, like #[derive(Debug)].
A struct cannot print itself yet
Nothing gives Point a Debug form yet, so the {:?} call is an error. The field-by-field print below is the workaround:
struct Point {
x: i32,
y: i32,
}
fn main() {
let p = Point { x: 3, y: 7 };
// println!("{:?}", p); // error: Point has no Debug form
println!("point = ({}, {})", p.x, p.y);
}derive writes the Debug code
One attribute above the struct asks the compiler to write its Debug form:
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let p = Point { x: 3, y: 7 };
println!("{:?}", p);
}Several traits in one attribute
Clone, Copy and PartialEq can all ride in the same derive. Copy makes the assignment copy the point, so both names stay usable:
#[derive(Debug, Clone, Copy, PartialEq)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let a = Point { x: 3, y: 7 };
let b = a;
println!("a = {:?} b = {:?}", a, b);
println!("equal = {}", a == b);
}#[allow] quiets one warning
An unused function earns a dead_code warning. #[allow(dead_code)] tells the compiler that this one is fine:
#[allow(dead_code)]
fn someday() {
println!("not yet");
}
fn main() {
println!("program runs");
}Example
#[derive(Debug, Clone, PartialEq)]
struct Team {
name: String,
wins: u32,
}
fn main() {
let reds = Team { name: String::from("Reds"), wins: 4 };
let copy = reds.clone();
println!("{:?}", reds);
println!("same team = {}", reds == copy);
}Key points
- An attribute changes what the compiler does with the item below it.
- derive asks the compiler to write a trait for the item below it.
- One attribute can derive several traits at once, separated by commas.
- #[allow(name)] switches off one named warning for the item below it.
- Attributes do their work while compiling, not while the program runs.
In this example, one derive attribute sits above Team. It asks for three traits at once: Debug, Clone, and PartialEq. Debug lets {:?} print the whole struct. Clone makes the copy that clone() returns. PartialEq makes the == test possible, and it answers true. Rust Attributes, in the Intermediate course, goes deeper from here — attributes that mark, switch, and reshape code.
Note
Other languages call similar marks annotations or decorators.
A Rust derive writes real code, not just a label.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Rust Playground
Exercise
What does #[derive(Clone)] ask the compiler to do?