Files
100-exercises-to-learn-rust/book/src/05_ticket_v2/09_error_trait.md
mckzm 2765fdaa0e Fix reference to supertrait syntax in 09_error_trait.md (#124)
The [Error trait](https://rust-exercises.com/100-exercises/05_ticket_v2/09_error_trait.html?highlight=supertrait#the-error-trait) chapter states that the reader may recall the supertrait syntax from the [Sized trait](https://rust-exercises.com/100-exercises/04_traits/08_sized) chapter. Actually the syntax is introduced in the [From and Into](https://rust-exercises.com/100-exercises/04_traits/09_from) chapter instead. This PR amends the text accordingly.
2024-08-05 17:53:07 +02:00

2.1 KiB
Raw Blame History

Error trait

Error reporting

In the previous exercise you had to destructure the TitleError variant to extract the error message and pass it to the panic! macro.
This is a (rudimentary) example of error reporting: transforming an error type into a representation that can be shown to a user, a service operator, or a developer.

Its not practical for each Rust developer to come up with their own error reporting strategy: itd be a waste of time and it wouldnt compose well across projects. Thats why Rust provides the std::error::Error trait.

The Error trait

There are no constraints on the type of the Err variant in a Result, but its a good practice to use a type that implements the Error trait. Error is the cornerstone of Rusts error handling story:

// Slightly simplified definition of the `Error` trait
pub trait Error: Debug + Display {}

You might recall the : syntax from the From trait—its used to specify supertraits. For Error, there are two supertraits: Debug and Display. If a type wants to implement Error, it must also implement Debug and Display.

Display and Debug

Weve already encountered the Debug trait in a previous exercise—its the trait used by assert_eq! to display the values of the variables its comparing when the assertion fails.

From a “mechanical” perspective, Display and Debug are identical—they encode how a type should be converted into a string-like representation:

// `Debug`
pub trait Debug {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>;
}

// `Display`
pub trait Display {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>;
}

The difference is in their purpose: Display returns a representation thats meant for “end-users”, while Debug provides a low-level representation thats more suitable to developers and service operators.
Thats why Debug can be automatically implemented using the #[derive(Debug)] attribute, while Display requires a manual implementation.