3 ms·
Not true, it's not "erased", it's wrapped. The original error is available via the `.inner` Wherr struct field.
by JoelJacobson 3y ago
Not true, it's not "erased", it's wrapped. The original error is available via the `.inner` Wherr struct field.
- vore 3y agoConsider 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.