liveBook · Manning

Derive macro

As explained in Refactoring to Rust

A derive is a Rust compiler directive that generates implementations of selected traits for a type.

A derive is a Rust compiler directive that generates an implementation of a selected trait for a type. Deriving Debug lets Rust print an Error value in a developer-useful representation. section 2.5.6

The FizzBuzz error path shows the practical progression:

  • Calling unwrap on Result requires the error type to implement Debug; without it, compilation fails. section 2.5.6
  • Adding #[derive(Debug)] to Error satisfies that requirement and makes the panic include GotNegative. section 2.5.6
  • Derive simplifies this common implementation, while larger programs still need proper error handling instead of routine panics. section 2.5.6

Deriving Debug for an error enum

#[derive(Debug)] enum Error { GotNegative, } fn print_fizzbuzz(x: i32) { match fizzbuzz(x).unwrap() { // handle the successful FizzBuzz result } } With Debug derived, a negative input panics with the error value: GotNegative. section 2.5.6

Listing 2.37 Panicking when print_fizzbuzz sees an error
enum FizzBuzzValue {
  Fizz,
  Buzz,
  FizzBuzz,
  NotDivisible(i32),
}

enum Error {
  GotNegative,
}

fn main() {
  print_fizzbuzz(-1);  #1
}

fn print_fizzbuzz(x: i32) {  #2
  match fizzbuzz(x) {
    Ok(result) => match result {
      FizzBuzzValue::FizzBuzz => {
        println!("FizzBuzz");
      }
      FizzBuzzValue::Fizz => {
        println!("Fizz");
      }
      FizzBuzzValue::Buzz => {
        println!("Buzz");
      }
      FizzBuzzValue::NotDivisible(num) => {
        println!("{}", num);
      }
 #3
    },
    Err(Error::GotNegative) => {
      panic!("Got a negative number for fizzbuzz: {}", x);
    }
  }
}

fn fizzbuzz(x: i32) -> Result<FizzBuzzValue, Error> {
  if x < 0 {
    Err(Error::GotNegative)
  } else if x % 3 == 0 && x % 5 == 0 {
    Ok(FizzBuzzValue::FizzBuzz)
  } else if x % 3 == 0 {
    Ok(FizzBuzzValue::Fizz)
  } else if x % 5 == 0 {
    Ok(FizzBuzzValue::Buzz)
  } else {
    Ok(FizzBuzzValue::NotDivisible(x))
  }
}

Compare the original FizzBuzz error-handling code with the shorter unwrap-based form that uses a derived Debug implementation. section 2.5.6

How Refactoring to Rust covers it

How deep it goes
Defines compiler-generated trait implementations and demonstrates Debug through compilation errors and panic output, without covering custom derive mechanics.
Examples
Uses a FizzBuzz Error enum with GotNegative, #[derive(Debug)], cargo run, and compiler and panic diagnostics.
What it assumes
Assumes basic Rust enums and Result usage while introducing traits and compiler directives only at the point of need.
What you can do after
Apply it via #[derive(Debug)] to make an error type satisfy unwrap's Debug requirement and produce readable panic output.
How it connects
Connects derive to Rust traits, Debug, Result, unwrap, enums, and panic-based error handling.

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 Refactoring to Rust. The section links point to the parts of the book it draws on.