How to deal with errors that don't implement the Error trait? #493
-
|
I'm new to Snafu, and did several standard tests to get the hang of it and managed to use it. I'm using a library where the Error is an enum that only has derive Debug (also generic over another error, but I don't think it's relevant here). Let's say it is: #[derive(Debug)]
enum LibError {
FirstError,
SecondError,
}I want to have my own error type defined in my code that uses that library. #[derive(Debug, Snafu)]
enum CallerError {
MyErrorError {
source: LibError
},
}The definition above errros with: If I replace LibError with some standard Error, ParseIntError for example it work. So it's probably due to the LibError not implementing Error trait. I tried using So I'm trying to figure out what's the correct way to use Snafu under such library error type. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 4 replies
-
Yes, that's correct. That's what Unfortunately, this isn't anything particularly special about The best thing to do is to poke the maintainers of In the meantime, you can write a little wrapper that implements use core::fmt;
use snafu::prelude::*;
#[derive(Debug)]
enum LibError {
FirstError,
SecondError,
}
struct LibErrorWrap(LibError);
impl core::error::Error for LibErrorWrap {}
impl fmt::Debug for LibErrorWrap {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl fmt::Display for LibErrorWrap {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
#[derive(Debug, Snafu)]
enum CallerError {
MyErrorError {
#[snafu(source(from(LibError, LibErrorWrap)))]
source: LibErrorWrap,
},
}That will allow you to use it as usual: fn myfn() -> Result<(), CallerError> {
libfn().context(MySnafu)
} |
Beta Was this translation helpful? Give feedback.
-
|
Ok, I was able to use the above to deal with my error using context. Now I'm looking for how to use Snafu under the same constraints with errors not implementing Error trait, for the simple case when I don't need source, and want an ergonomic error handling. use of I just want to create an Error enum, and then have the error from the underlying library to automatically convert to my Error enum, by me specifying the type of error the underlying library error should be converted to. Is it possible with snafu, or do I need to be explicit? I found the following options below: one doesn't seem very ergonomic ( #[derive(Snafu, Debug)]
pub enum Error {
#[snafu(display("Too many store operations pending"))]
TooManyOps
}
impl Store {
pub fn try_submit_op(&self, op: StoreOp) -> Result<(), Error> {
let res = self.requests_channel.try_send(op);
ensure!(res.is_err(), TooManyOpsSnafu); // <---- Snafu, doesn't feel very convenient to use
res.map_err(|_| Error::TooManyOps)?; // Doesn't take advantage of Snafu
// res?; // <---- This is how I would want it to work in this case, but it doesn't
// res.context(TooManyOpsSnafu)?; // <--- or even this would be nicer/easier than the first two, but requires source
Ok(())
}
} |
Beta Was this translation helpful? Give feedback.
Perhaps, but assuming that each maintainer has 2+ users, the total impact would be much greater for them to perform the change.
Maybe? There's not really anything special about the wrapper I showed; you could likely make it generic and use it in a number of places, assuming that all the other errors also implement
Debugas the common thing.