I don't like having to wrap my function with a macro, with all disadvantages (e.g. worse IDE support), just to get error location. Especially given we can do this without macros at all:<p><pre><code> use std::error::Error as StdError;
use std::panic::Location;
use std::fmt;
#[derive(Debug)]
pub struct MyError {
pub error: Box<dyn StdError + Send + Sync>,
pub location: &'static Location<'static>,
}
impl<E: StdError + Send + Sync + 'static> From<E> for MyError {
#[track_caller]
#[inline]
fn from(error: E) -> Self {
Self {
error: Box::new(error),
location: Location::caller(),
}
}
}
impl fmt::Display for MyError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}, {}", self.error, self.location)
}
}
</code></pre>
We can also optimize this more (e.g. a simple optimization to be two words instead of three: <a href="https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=2a46e8a71103b4a2f432defc320dc06a" rel="nofollow noreferrer">https://play.rust-lang.org/?version=stable&mode=debug&editio...</a>. Also allows opting `Send` and `Sync` out or using non-`'static` lifetimes), but this works as a baseline. The only disadvantage is that if called in a function with `#[track_caller]` this will report the location of the caller... But this is something I can live with.