Stacked Errors
This is an errors crate with the purpose to provide better error debuggability in async
call
stacks (backtraces are basically useless in async
tasks). What we do is take advantage of
#[track_caller]
and create a stack of Location
s and errors via the helpful StackableErr
trait.
use ;
// Note that `Error` uses `ThinVec` internally, which means that it often
// takes up only the stack space of a `usize` or the size of the `T` plus
// a byte.
let res = format!;
assert_eq!;
// The line numbers are slightly off because this is a doc test.
// In order from outer to the innermost call, it lists the location of the
// `stack` call from `outer`, the location of `stack_err` from `inner`,
// the associated error message, the location of either the `Error::from`
// or `stack_err` from `innermost`, and finally the root error message.
let res = format!;
assert_eq!;
let res = format!;
assert_eq!;
Some other partial examples of what using the crate properly looks like:
f.map_err?;
// replace the above with
f.stack?;
f.stack_err?;
// replace the above with
f.stack?;
// if needing to push another arbitrary error onto the stack
f.stack_err?;
let dir = self
.path
.parent
.stack_err?
.to_str
.stack_err?;
option.take
.stack_err?
.wait_with_output
.await
.stack_err?;
// strings and some std errors can be created like this,
return Err
// otherwise use this (also note that `Error::from*` includes
// `#[track_caller]` location, no need to add on a `stack` call)
return Err
// when the error type is already `crate::Error` you can do this if it is
// preferable over `map`
return match ...
// in commonly used functions you may want `_locationless` to avoid adding
// on unnecessary information if the location is already being added on
return Err.stack_err