On 10/19 I wrote about recoverable errors with the question mark operator. The question mark calls the into() method when an error is matched.

match File::create("foo.txt") {
    Ok(t)  => t.write_all(b"Hello world!"),
    Err(e) => return Err(e.into()),
}

In WeeRust, I leverage the question mark operator to map multiple error types into a unified type AppErr. The type lettre::transport::smtp::Error and async_imap::error::Error are different types from different crates, however, when into() is called on either of these types, the type is transformed into AppErr with a variant of either ImapError or SmtpError. More generally, Into<U> for T where U is AppErr and T is either lettre::transport::smtp::Error or async_imap::error::Error.

The Into implementation is provided by the From trait. For example, in WeeRust, lettre::transport::smtp::Error implements the From trait (for the AppErr enum) as follows:

 impl From<lettre::transport::smtp::Error> for AppErr {
      fn from(error: lettre::transport::smtp::Error) -> Self {
          AppErr::SmtpError(error)
      }
  }

After implementing the above example, calling into() on a type lettre::transport::smtp::Error will result in a variant AppErr::SmtpError(lettre::transport::smtp::Error) of type AppErr.

Example credit