---
title: "16.5 Deriving traits"
description: "A tour of the derivable traits (Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default), what each unlocks, and when you can't derive."
url: "https://learnrust.net/chapter-16/deriving-traits/"
last_updated: "2026-06-13"
---

# 16.5 Deriving traits

For many common traits, the implementation is mechanical: there's an obvious correct version the compiler can write from your type's definition. `#[derive(...)]` is how you ask it to. You've used `derive` since lesson [10.7](https://learnrust.net/chapter-10/deriving-debug/) for `Debug`; now that you know what a trait *is*, this lesson tours the derivable traits and what each one gives you. Think of it as the menu.

## How derive works

`#[derive(Trait)]` above a type tells the compiler: "write the standard implementation of `Trait` for this type." It works field by field, deriving the trait for the whole struct or enum by combining its behavior on each field. That's why a struct can only derive a trait if *all its fields* already implement it; the derived implementation is built out of the fields' implementations.

```rust
#[derive(Debug, Clone, PartialEq)]
struct Point {
    x: f64,
    y: f64,
}
```

This one line gives `Point` three behaviors: printable with `{:?}`, cloneable with `.clone()`, and comparable with `==`. Each would be tedious and error-prone to write by hand, and the compiler's version is exactly what you'd write anyway.

## The tour

The traits you can derive, and what each unlocks:

**`Debug`** enables `{:?}` and `{:#?}` formatting (lesson [10.7](https://learnrust.net/chapter-10/deriving-debug/)) and makes the type usable with `dbg!` and `assert_eq!` failure messages. Derive it on essentially every type; the cost is nothing and the debugging payoff is constant.

**`Clone`** enables `.clone()`, an explicit deep copy (lesson [8.7](https://learnrust.net/chapter-8/clone/)). Derive it when you need independent copies of a value.

**`Copy`** makes the type copy implicitly on assignment instead of moving (lesson [8.5](https://learnrust.net/chapter-8/copy-types/)). It requires `Clone` too (`#[derive(Copy, Clone)]` together) and is only allowed when every field is `Copy`, so a struct containing a `String` can never be `Copy`. Derive it on small, all-`Copy` types like a `Point` of numbers.

**`PartialEq`** enables `==` and `!=`. **`Eq`** is a marker added on top (`#[derive(PartialEq, Eq)]`) that promises equality is "total", every value equals itself, which floats notably *don't* satisfy because `NaN != NaN` (lesson [4.5](https://learnrust.net/chapter-4/floating-point-types/)). So a type with an `f64` field can derive `PartialEq` but not `Eq`.

**`PartialOrd`** enables the comparison operators `<`, `>`, `<=`, `>=` (the trait that finished `largest` in lesson [16.3](https://learnrust.net/chapter-16/trait-bounds/)). **`Ord`** adds total ordering on top (requires `Eq` and `PartialOrd`), needed to sort or to use as a sorted-collection key. For a struct, the derived ordering compares fields in declaration order, like comparing tuples.

**`Hash`** lets a type be used as a `HashMap` key (lesson [18.6](https://learnrust.net/chapter-18/hashmap/)).

**`Default`** provides `::default()`, every field at its default value (lesson [10.6](https://learnrust.net/chapter-10/associated-functions-and-constructors/)).

> **Key insight**
>
> `derive` is the compiler writing the obvious implementation so you don't. The rule of thumb behind which traits are derivable: a trait is derivable when "do it for each field and combine" is unambiguously the right implementation. `Debug` (show each field), `Clone` (clone each field), `PartialEq` (compare each field), `Default` (default each field), all fit. A trait like `Display` (lesson [16.6](https://learnrust.net/chapter-16/display-and-tostring/)) is *not* derivable, because there's no obvious single way to present a type to humans, that one you must write.

## A common derive set

In practice a few derives appear together so often they're almost reflexive. For a plain data type you'll frequently write:

```rust
#[derive(Debug, Clone, PartialEq)]
struct Config {
    name: String,
    retries: u32,
}
```

`Debug` for inspection, `Clone` for making copies, `PartialEq` so you can compare (and so `assert_eq!` works in tests, lesson [14.2](https://learnrust.net/chapter-14/writing-tests/)). Add `Default` if a "zeroed" instance makes sense, `Eq + Hash` if it'll be a map key, `Copy + Clone` if it's small and all-`Copy`. You add derives as you discover you need the capability; the compiler's error messages tell you which trait is missing when you try to do something the type can't yet.

## When you can't derive

Two situations stop a derive. First, **a field doesn't implement the trait**: you can't derive `Clone` for a struct whose field isn't `Clone`, because the field-by-field implementation has nothing to call. The fix is to make the field cloneable or implement `Clone` by hand. Second, **the derived behavior isn't what you want**: the mechanical version is correct but not appropriate, for instance two `Color` values that should compare equal if their RGB matches regardless of an attached name field. When the obvious implementation is wrong for your type, skip the derive and write `impl Trait for Type` by hand, exactly as you did for `Summary` in lesson [16.1](https://learnrust.net/chapter-16/introduction-to-traits/). Derive is a convenience, never an obligation.

## Quiz time

**Question #1**

Why can a struct derive a trait only if all its fields implement that trait?

<details class="solution">
<summary>Show solution</summary>

Because the derived implementation is built field by field: deriving `Clone` clones each field, deriving `PartialEq` compares each field, and so on. If a field doesn't implement the trait, there's nothing for the derived code to call on that field, so the derive can't be generated. The whole is assembled from the parts.

</details>

**Question #2**

Your struct has an `f64` field. Can you derive `PartialEq`? Can you derive `Eq`? Why?

<details class="solution">
<summary>Show solution</summary>

You can derive `PartialEq` (floats support `==`), but not `Eq`. `Eq` promises *total* equality, where every value equals itself, and floats violate that because `NaN != NaN` (lesson [4.5](https://learnrust.net/chapter-4/floating-point-types/)). So `f64` implements `PartialEq` but not `Eq`, and a struct containing one inherits that limitation.

</details>

**Question #3**

When should you write a trait implementation by hand instead of deriving it?

<details class="solution">
<summary>Show solution</summary>

When the mechanical field-by-field version isn't what you want (e.g. equality that should ignore some field, or a custom ordering), or when the trait isn't derivable at all (like `Display`, which has no obvious automatic form). Also when a field doesn't implement the trait and you need custom handling. Derive when the obvious implementation is right; hand-write when it isn't.

</details>

`Display` was the one trait this lesson said you *can't* derive. The next lesson implements it by hand, the controlled, human-facing `{}` output you've wanted since lesson [10.7](https://learnrust.net/chapter-10/deriving-debug/), and the Rust version of C++'s "overloading `operator<<`."

## Sitemap

See the full [sitemap](https://learnrust.net/sitemap.md) for all pages.
