liveBook · Manning

Derive macro

As explained in Learn Rust in a Month of Lunches

A derive attribute is a Rust attribute that requests automatic implementation of specified traits for a type.

A derive macro asks Rust to implement a trait for a type automatically. Write `#[derive(Debug)]` immediately above a struct or enum to give it `Debug`, which lets you print it with `{:?}`. The `#[...]` syntax is an attribute: a message to the compiler about the item that follows. section 4.1.5 section 7.1

#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Clone)]
struct HoldsAString {
    the_string: String,
}
 
fn main() {
    let my_string = HoldsAString {
        the_string: "Here I am!".to_string(),
    };
    println!("{:?}", my_string);
}

This struct requests several trait implementations in one `derive` attribute. The final line uses its derived `Debug` implementation to print the value. section 13.1.5

Deriving saves you from writing an implementation yourself when Rust can supply one. `Debug`, for example, needs a `fmt` method, but you will usually derive it rather than write that method. You can also derive `Clone` and `Copy` for the small struct shown in the attributes examples. section 13.1.4 section 13.1.5

When derive does not work

Trying `#[derive(Display)]` in the shown example produces `cannot find derive macro Display in this scope`. Not every trait can be derived: Rust cannot guess what adding two values of a custom type should mean, so `Add` needs a manual `impl`. section 13.1.5 section 7.1

#[derive(Clone, Debug)]
struct File(String);
 
impl std::fmt::Display for File {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let as_bytes = format!("{:?}", self.0.as_bytes());               #1
        write!(f, "{as_bytes}")
    }
}
 
fn main() {
    let file = File(String::from("I am file contents"));
    println!("{file:?}");
    println!("{file}");
}

A wrapper around `String` does not automatically gain `String`’s traits. Here it derives `Clone` and `Debug`, while `Display` gets a handwritten implementation. section 7.4

How Learn Rust in a Month of Lunches covers it

How deep it goes
Explains attribute placement, multiple derives, compiler feedback, and when manual implementations are needed; does not teach writing derive macros.
Examples
Shows Debug-printed types, a struct deriving several traits, a failed Display derive, and a newtype combining derived and manual implementations.
What it assumes
Builds on structs, enums, and traits while defining attributes and automatic trait implementation in plain terms.
What you can do after
Apply it via Rust’s `#[derive(...)]` attribute to request supported traits and recognize when a manual implementation is needed.
How it connects
Connects derive to traits, structs, enums, Debug formatting, manual impl blocks, and newtypes.

Also explained in

Compare how 5 books explain derive macro →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Rust in a Month of Lunches. The section links point to the parts of the book it draws on.