Result<T, E>
is an enum
type which has two variants: Ok(T)
indicating successful execution with meaningful result of type T
, and Err(E)
indicating occurrence of an unexpected error during execution, described by a value of type E
.
enum DateError {
InvalidDay,
InvalidMonth,
}
struct Date {
day: u8,
month: u8,
year: i16,
}
fn validate(date: &Date) -> Result<(), DateError> {
if date.month < 1 || date.month > 12 {
Err(DateError::InvalidMonth)
} else if date.day < 1 || date.day > 31 {
Err(DateError::InvalidDay)
} else {
Ok(())
}
}
fn add_days(date: Date, days: i32) -> Result<Date, DateError> {
validate(&date)?; // notice `?` -- returns early on error
// the date logic ...
Ok(date)
}
Also see docs for more details on ?
operator.
Standard library contains an Error
trait which all error types are recommended to implement. An example implementation is given below.
use std::error::Error;
use std::fmt;
#[derive(Debug)]
enum DateError {
InvalidDay(u8),
InvalidMonth(u8),
}
impl fmt::Display for DateError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&DateError::InvalidDay(day) => write!(f, "Day {} is outside range!", day),
&DateError::InvalidMonth(month) => write!(f, "Month {} is outside range!", month),
}
}
}
impl Error for DateError {
fn description(&self) -> &str {
match self {
&DateError::InvalidDay(_) => "Day is outside range!",
&DateError::InvalidMonth(_) => "Month is outside range!",
}
}
// cause method returns None by default
}
Note: Generally, Option<T>
should not be used for reporting errors. Option<T>
indicates an expected possibility of non-existence of a value and a single straightforward reason for it. In contrast, Result<T, E>
is used to report unexpected errors during execution, and especially when there are multiple modes of failures to distinguish between them. Furthermore, Result<T, E>
is only used as return values. (An old discussion.)