backtrace() delegation
sergiimk opened this issue · comments
When wrapping one error that has a Backtrace
with another error via #[from]
without a backtrace field I'd expect outer error's Error::backtrace()
method to return inner error's backtrace.
Example:
#![feature(backtrace)]
use std::backtrace::Backtrace;
use std::error::Error as StdError;
use std::fs::File;
use thiserror::Error;
#[derive(Error, Debug)]
enum MyErrorFoo {
#[error("IO error: {source}")]
IoError {
#[from]
source: std::io::Error,
backtrace: Backtrace,
},
}
#[derive(Error, Debug)]
enum MyErrorBar {
#[error("Foo error: {0}")]
FooError(#[from] MyErrorFoo),
}
fn foo() -> Result<(), MyErrorFoo> {
File::open("/doesnt_exist")?;
Ok(())
}
fn bar() -> Result<(), MyErrorBar> {
foo()?;
Ok(())
}
fn main() {
let e_foo = foo().unwrap_err();
assert!(e_foo.backtrace().is_some()); // PASSES
let e_bar = bar().unwrap_err();
match e_bar {
MyErrorBar::FooError(ref inner) => assert!(inner.backtrace().is_some()), // PASSES
};
assert!(e_bar.backtrace().is_some()); // FAILS
}
I get same results when I tag backtrace
field with #[backtrace]
and when I tag FooError(#[from] MyErrorFoo)
with #[transparent]
.
// PS: Thank you for a great library!
I might've been thinking the wrong way about this.
Rather than thinking of top-level error as a wrapper around the original error I should've been thinking of it as a chain of linked errors where some errors in the chain may have their own backtraces, so my error reporting code should not be relying on top-level's error's backtrace but rather should dig through this chain and pick which traces to display.
Appologies for confusion.