Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Deriving and Common Trait Implementations

Rule

Derive standard traits when their semantics are obvious, hand-write Display, and avoid semantics-heavy derives by habit.

Why

Derived impls are correct when structural behavior matches domain behavior; otherwise they can expose secrets or promise misleading equality, ordering, defaults, or clone semantics.

Do

  • Derive Debug for ordinary data and redact secret-bearing types manually.
  • Derive Clone for value semantics with acceptable cost.
  • Derive Copy only for small scalar-like values with unsurprising duplication.
  • Derive equality and hashing only when the same fields define both.
  • Derive ordering only when one total order is obvious.
  • Implement Default only for a valid, useful, unsurprising value.
  • Hand-write Display for stable user-facing text.
  • Keep manual equality, hashing, and ordering implementations coherent.

Avoid

  • Do not derive traits solely to satisfy a temporary test or log statement.
  • Do not derive Debug for credentials or tokens.
  • Do not derive Copy for resources or types likely to gain owned data.
  • Do not derive arbitrary ordering or invalid defaults.
  • Do not use Display for programmer-only diagnostics.
  • Do not derive serialization unless a wire format is intentional.

Public API Notes

Public trait impls are compatibility surface. Add only semantics the type can support over time.

Example

#![allow(unused)]
fn main() {
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct UserId(u64);

#[derive(Clone, Eq, PartialEq)]
pub struct ApiToken(String);

impl std::fmt::Debug for ApiToken {
    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        formatter.write_str("ApiToken(<redacted>)")
    }
}
}

Exceptions

  • Keep impl surface smaller while a public type’s semantics are unsettled.
  • Add derives freely to test-only helpers when they do not leak into production API.
  • Hand-write traits when domain behavior differs from field-by-field behavior.