The #[derive(...)] attribute asks the compiler to generate implementations, commonly for traits such as Clone, Debug, and Default. It reduces boilerplate on structs and enums; write a manual implementation when you need behavior the derived one does not provide. section 2.2.5 section 8.3
use std::fmt::Debug;
#[derive(Clone, Debug, Default)]
struct Pumpkin {
mass: f64,
diameter: f64,
}
A struct deriving Clone, Debug, and Default shows the attribute in its simplest form. section 2.2.5
A custom derive is a procedural macro written in a separate library crate. It receives Rust syntax and returns generated Rust syntax at compile time; derive macros attach to struct or enum declarations. section 8.3
Listing 8.9 Implementing the PrintName derive macro
#[proc_macro_derive(PrintName)]
pub fn print_name(input: TokenStream) -> TokenStream { #1
let input = parse_macro_input!(input as DeriveInput); #1
let generics = add_trait_bounds(input.generics); #2
let (impl_generics, type_generics, where_clause) = #3
generics.split_for_impl(); #3
let name = input.ident;
let expanded = quote! { #4
impl #impl_generics print_name::PrintName for #name #type_generics
#where_clause {
fn name() -> &'static str {
stringify!(#name) #5
}
}
};
TokenStream::from(expanded) #6
}
fn add_trait_bounds(mut generics: Generics) -> Generics {
for param in &mut generics.params {
if let GenericParam::Type(ref mut type_param) = *param {
type_param.bounds.push( #7
parse_quote!(print_name::PrintName) #7
); #7
}
}
generics
}
This implementation parses a derive input and generates a trait implementation, including handling generics. section 8.3
Choose a manual implementation for custom defaults
A derived Default creates a zeroed Pumpkin. To give it a mass of 2.0 and diameter of 5.0 instead, replace the derive with an explicit Default implementation. section 2.2.5




