| Crates.io | pseudo-backtrace |
| lib.rs | pseudo-backtrace |
| version | 0.2.1 |
| created_at | 2025-09-30 15:32:27.444731+00 |
| updated_at | 2025-10-01 15:26:48.585261+00 |
| description | Utilities for constructing stack-like error chains with caller locations |
| homepage | |
| repository | https://github.com/tunamaguro/pseudo-backtrace |
| max_upload_size | |
| id | 1861288 |
| size | 68,409 |
This is a library that makes it easy to create error types that can track error propagation history.
use pseudo_backtrace::{StackError, StackErrorExt};
#[derive(Debug)]
pub struct ErrorA(());
impl core::fmt::Display for ErrorA {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
"ErrorA".fmt(f)
}
}
impl core::error::Error for ErrorA {}
#[derive(Debug, StackError)]
pub struct ErrorB {
#[stack_error(std)]
source: ErrorA,
location: &'static core::panic::Location<'static>,
}
impl core::fmt::Display for ErrorB {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
"ErrorB".fmt(f)
}
}
impl core::error::Error for ErrorB {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(&self.source)
}
}
impl From<ErrorA> for ErrorB {
#[track_caller]
fn from(value: ErrorA) -> Self {
ErrorB {
source: value,
location: core::panic::Location::caller(),
}
}
}
#[derive(Debug, StackError)]
pub struct ErrorC {
source: ErrorB,
location: &'static core::panic::Location<'static>,
}
impl core::fmt::Display for ErrorC {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
"ErrorC".fmt(f)
}
}
impl core::error::Error for ErrorC {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(&self.source)
}
}
impl From<ErrorB> for ErrorC {
#[track_caller]
fn from(value: ErrorB) -> Self {
ErrorC {
source: value,
location: core::panic::Location::caller(),
}
}
}
# fn main() {
let a = ErrorA(());
let b = ErrorB::from(a);
let c = ErrorC::from(b);
println!("{}", c.to_chain())
// will be printed to standard output as follows:
// 0: ErrorC, at examples/simple.rs:74:13
// 1: ErrorB, at examples/simple.rs:73:13
// 2: ErrorA
# }
#[derive(StackError)]Deriving StackError requires two types of fields:
Required Field:
&'static core::panic::Location<'static>. This is mandatory.location or marked with the #[location] attribute.Optional Field:
#[stack_error(std)]: Treats the next error as a type implementing core::error::Error.#[stack_error(stacked)]: Treats the next error as a type implementing StackError.#[source] or a field named source: Defaults to #[stack_error(stacked)].Note that the macro only implements StackError, so users must manually implement core::error::Error.
LocatedError as both location and sourceYou can embed a LocatedError<T> field and use it for both the location and the source in one of the following ways:
#[derive(Debug, pseudo_backtrace::StackError)]
pub struct WrappedIo {
#[location]
#[source] // or `#[stack_error(stacked)]` / `#[stack_error(std)]`
inner: pseudo_backtrace::LocatedError<std::io::Error>,
}
impl core::fmt::Display for WrappedIo {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "wrapped-io")
}
}
impl core::error::Error for WrappedIo {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(&self.inner)
}
}
#[location], the derive will automatically use the #[source] field when its type is LocatedError<_> as the location provider:#[derive(Debug, pseudo_backtrace::StackError)]
pub struct WrappedIo {
#[source]
inner: pseudo_backtrace::LocatedError<std::io::Error>,
}
impl core::fmt::Display for WrappedIo {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "wrapped-io")
}
}
impl core::error::Error for WrappedIo {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(&self.inner)
}
}
In both cases, the generated impl StackError will return inner.location() as the location and will chain to inner as the next error.