4 ms·
Consider this: #[derive(Debug)] enum MyError { A, B, C } impl std::fmt::Display for MyError { fn fmt(&self, f: &mut std::fmt::
by vore 3y ago
Consider this:
#[derive(Debug)]
enum MyError {
A,
B,
C
}
impl std::fmt::Display for MyError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
impl std::error::Error for MyError {}
// Equivalent to wherr::Wherr.
#[derive(Debug)]
struct ErrorWrapper {
inner: Box<dyn std::error::Error>
}
impl std::fmt::Display for ErrorWrapper {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
self.inner.fmt(f)
}
}
impl std::error::Error for ErrorWrapper {}
fn my_error() -> Result<(), MyError> {
Err(MyError::A)?
}
// Equivalent to applying #[wherr] to my_error.
fn my_error_wrapped() -> Result<(), ErrorWrapper> {
Err(ErrorWrapper { inner: Box::new(MyError::A) })?
}
fn main() {
// Works.
match my_error().unwrap_err() {
MyError::A => { println!("got MyError::A"); }
_ => { println!("got some other MyError variant"); }
}
// Doesn't work: how do I match out the inner MyError?
match my_error_wrapped().unwrap_err().inner {
MyError::A => { println!("got MyError::A"); }
_ => { println!("got some other MyError variant"); }
}
}
- JoelJacobson 3y ago// This will work: downcast the inner error and then match on it. match my_error_wrapped().unwrap_err().inner.downcast_ref::<MyError>() { Some(MyError::A) => println!("got MyError::A"), Some(_) => println!("got some other MyError variant"), None => println!("got an unknown error type"), }
- vore 3y agoI think, at that point, you should rather make Wherr be `struct Wherr<E> { inner: E, ... }` to avoid having to do a dynamic cast - I don't personally like the idea of erasing guarantees of what types you're getting.
- JoelJacobson 3y agoThat seems like a great idea. I've started a branch "attempt_to_avoid_dynamic_cast" where I've tried to implement your idea: https://github.com/joelonsql/wherr/commit/c5906a257fc9768ad0add455bbc89107d4e7d978 https://github.com/joelonsql/wherr/commit/c5906a257fc9768ad0... I couldn't figure out how to make it work though, since with these changes, now nested functions using the #[wherr] macro won't work due to "doesn't have a size known at compile-time". The other idea of just using #[track_caller] also seems promising, and will be considered for a future major version. But I still think it's interesting if the macro variant can be improved, to avoid having to do dynamic casts, hence this new branch.