| ## Appendix C: Derivable Traits |
| |
| In various places in the book, we’ve discussed the `derive` attribute, which you |
| can apply to a struct or enum definition. The `derive` attribute generates code |
| that will implement a trait with its own default implementation on the type |
| you’ve annotated with the `derive` syntax. |
| |
| In this appendix, we provide a reference of all the traits in the standard |
| library that you can use with `derive`. Each section covers: |
| |
| * What operators and methods deriving this trait will enable |
| * What the implementation of the trait provided by `derive` does |
| * What implementing the trait signifies about the type |
| * The conditions in which you’re allowed or not allowed to implement the trait |
| * Examples of operations that require the trait |
| |
| If you want different behavior from that provided by the `derive` attribute, |
| consult the [standard library documentation](../std/index.html)<!-- ignore --> |
| for each trait for details of how to manually implement them. |
| |
| These traits listed here are the only ones defined by the standard library that |
| can be implemented on your types using `derive`. Other traits defined in the |
| standard library don’t have sensible default behavior, so it’s up to you to |
| implement them in the way that makes sense for what you’re trying to accomplish. |
| |
| An example of a trait that can’t be derived is `Display`, which handles |
| formatting for end users. You should always consider the appropriate way to |
| display a type to an end user. What parts of the type should an end user be |
| allowed to see? What parts would they find relevant? What format of the data |
| would be most relevant to them? The Rust compiler doesn’t have this insight, so |
| it can’t provide appropriate default behavior for you. |
| |
| The list of derivable traits provided in this appendix is not comprehensive: |
| libraries can implement `derive` for their own traits, making the list of traits |
| you can use `derive` with truly open-ended. Implementing `derive` involves using |
| a procedural macro, which is covered in the [“Macros”][macros]<!-- ignore --> |
| section of Chapter 20. |
| |
| ### `Debug` for Programmer Output |
| |
| The `Debug` trait enables debug formatting in format strings, which you indicate |
| by adding `:?` within `{}` placeholders. |
| |
| The `Debug` trait allows you to print instances of a type for debugging |
| purposes, so you and other programmers using your type can inspect an instance |
| at a particular point in a program’s execution. |
| |
| The `Debug` trait is required, for example, in using the `assert_eq!` macro. |
| This macro prints the values of instances given as arguments if the equality |
| assertion fails so programmers can see why the two instances weren’t equal. |
| |
| ### `PartialEq` and `Eq` for Equality Comparisons |
| |
| The `PartialEq` trait allows you to compare instances of a type to check for |
| equality and enables use of the `==` and `!=` operators. |
| |
| Deriving `PartialEq` implements the `eq` method. When `PartialEq` is derived on |
| structs, two instances are equal only if _all_ fields are equal, and the |
| instances are not equal if any fields are not equal. When derived on enums, each |
| variant is equal to itself and not equal to the other variants. |
| |
| The `PartialEq` trait is required, for example, with the use of the `assert_eq!` |
| macro, which needs to be able to compare two instances of a type for equality. |
| |
| The `Eq` trait has no methods. Its purpose is to signal that for every value of |
| the annotated type, the value is equal to itself. The `Eq` trait can only be |
| applied to types that also implement `PartialEq`, although not all types that |
| implement `PartialEq` can implement `Eq`. One example of this is floating point |
| number types: the implementation of floating point numbers states that two |
| instances of the not-a-number (`NaN`) value are not equal to each other. |
| |
| An example of when `Eq` is required is for keys in a `HashMap<K, V>` so the |
| `HashMap<K, V>` can tell whether two keys are the same. |
| |
| ### `PartialOrd` and `Ord` for Ordering Comparisons |
| |
| The `PartialOrd` trait allows you to compare instances of a type for sorting |
| purposes. A type that implements `PartialOrd` can be used with the `<`, `>`, |
| `<=`, and `>=` operators. You can only apply the `PartialOrd` trait to types |
| that also implement `PartialEq`. |
| |
| Deriving `PartialOrd` implements the `partial_cmp` method, which returns an |
| `Option<Ordering>` that will be `None` when the values given don’t produce an |
| ordering. An example of a value that doesn’t produce an ordering, even though |
| most values of that type can be compared, is the not-a-number (`NaN`) floating |
| point value. Calling `partial_cmp` with any floating point number and the `NaN` |
| floating point value will return `None`. |
| |
| When derived on structs, `PartialOrd` compares two instances by comparing the |
| value in each field in the order in which the fields appear in the struct |
| definition. When derived on enums, variants of the enum declared earlier in the |
| enum definition are considered less than the variants listed later. |
| |
| The `PartialOrd` trait is required, for example, for the `gen_range` method from |
| the `rand` crate that generates a random value in the range specified by a range |
| expression. |
| |
| The `Ord` trait allows you to know that for any two values of the annotated |
| type, a valid ordering will exist. The `Ord` trait implements the `cmp` method, |
| which returns an `Ordering` rather than an `Option<Ordering>` because a valid |
| ordering will always be possible. You can only apply the `Ord` trait to types |
| that also implement `PartialOrd` and `Eq` (and `Eq` requires `PartialEq`). When |
| derived on structs and enums, `cmp` behaves the same way as the derived |
| implementation for `partial_cmp` does with `PartialOrd`. |
| |
| An example of when `Ord` is required is when storing values in a `BTreeSet<T>`, |
| a data structure that stores data based on the sort order of the values. |
| |
| ### `Clone` and `Copy` for Duplicating Values |
| |
| The `Clone` trait allows you to explicitly create a deep copy of a value, and |
| the duplication process might involve running arbitrary code and copying heap |
| data. See the |
| [“Ways Variables and Data Interact: |
| Clone”][ways-variables-and-data-interact-clone]<!-- ignore --> section in |
| Chapter 4 for more information on `Clone`. |
| |
| Deriving `Clone` implements the `clone` method, which when implemented for the |
| whole type, calls `clone` on each of the parts of the type. This means all the |
| fields or values in the type must also implement `Clone` to derive `Clone`. |
| |
| An example of when `Clone` is required is when calling the `to_vec` method on a |
| slice. The slice doesn’t own the type instances it contains, but the vector |
| returned from `to_vec` will need to own its instances, so `to_vec` calls `clone` |
| on each item. Thus, the type stored in the slice must implement `Clone`. |
| |
| The `Copy` trait allows you to duplicate a value by only copying bits stored on |
| the stack; no arbitrary code is necessary. See the |
| [“Stack-Only Data: Copy”][stack-only-data-copy]<!-- ignore --> section in |
| Chapter 4 for more information on `Copy`. |
| |
| The `Copy` trait doesn’t define any methods to prevent programmers from |
| overloading those methods and violating the assumption that no arbitrary code is |
| being run. That way, all programmers can assume that copying a value will be |
| very fast. |
| |
| You can derive `Copy` on any type whose parts all implement `Copy`. A type that |
| implements `Copy` must also implement `Clone`, because a type that implements |
| `Copy` has a trivial implementation of `Clone` that performs the same task as |
| `Copy`. |
| |
| The `Copy` trait is rarely required; types that implement `Copy` have |
| optimizations available, meaning you don’t have to call `clone`, which makes the |
| code more concise. |
| |
| Everything possible with `Copy` you can also accomplish with `Clone`, but the |
| code might be slower or have to use `clone` in places. |
| |
| ### `Hash` for Mapping a Value to a Value of Fixed Size |
| |
| The `Hash` trait allows you to take an instance of a type of arbitrary size and |
| map that instance to a value of fixed size using a hash function. Deriving |
| `Hash` implements the `hash` method. The derived implementation of the `hash` |
| method combines the result of calling `hash` on each of the parts of the type, |
| meaning all fields or values must also implement `Hash` to derive `Hash`. |
| |
| An example of when `Hash` is required is in storing keys in a `HashMap<K, V>` to |
| store data efficiently. |
| |
| ### `Default` for Default Values |
| |
| The `Default` trait allows you to create a default value for a type. Deriving |
| `Default` implements the `default` function. The derived implementation of the |
| `default` function calls the `default` function on each part of the type, |
| meaning all fields or values in the type must also implement `Default` to derive |
| `Default`. |
| |
| The `Default::default` function is commonly used in combination with the struct |
| update syntax discussed in the |
| [“Creating Instances From Other Instances With Struct Update |
| Syntax”][creating-instances-from-other-instances-with-struct-update-syntax]<!-- ignore --> |
| section in Chapter 5. You can customize a few fields of a struct and then set |
| and use a default value for the rest of the fields by using |
| `..Default::default()`. |
| |
| The `Default` trait is required when you use the method `unwrap_or_default` on |
| `Option<T>` instances, for example. If the `Option<T>` is `None`, the method |
| `unwrap_or_default` will return the result of `Default::default` for the type |
| `T` stored in the `Option<T>`. |
| |
| [creating-instances-from-other-instances-with-struct-update-syntax]: ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax |
| [stack-only-data-copy]: ch04-01-what-is-ownership.html#stack-only-data-copy |
| [ways-variables-and-data-interact-clone]: ch04-01-what-is-ownership.html#ways-variables-and-data-interact-clone |
| [macros]: ch20-06-macros.html#macros |