The Error trait is used by the standard library and most crates for their error types.
To implement the Error trait for a custom error we need to implement
the Debug and Display traits:
The
Debugimplementation can be done using thederive()macro.The
Displayimplementation must be done manually.The
Errorimplementation must just be declared, there is no method to implement.
First, we import the Error trait and the fmt (i.e.: format) module:
use std::error::Error;
use std::fmt;We declare a custom error, using here a struct with a single message
field, but an enum would do also. Note the implementation of the
Debug trait through the derive attribute:
#[derive(Debug)]
struct MyError {
msg: &'static str,
}We then implement the Display formatter trait that will allow to print
our error through the print!() and format!() macros:
impl fmt::Display for MyError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.msg)
}
}Finally, we implement the Error trait, which requires no method
definition:
impl Error for MyError {}Now we can define an example function that returns a Result that uses
our custom error:
fn foo(x: f32) -> Result<f32, MyError> {
if x > 1.0 {
Ok(2.0 * x)
} else {
Err(MyError { msg: "My error message." })
}
}Here is a usage of the foo() function with two different values:
for x in [0.2, 1.1] {
match foo(x) {
Ok(y) => println!("{y}"),
Err(e) => println!("{e}"),
}
}My error message.
2.2
()