pub struct Backtrace { /* private fields */ }Expand description
A backtrace that tracks error propagation through the call stack.
Backtrace stores a complete history of an error’s journey, including:
- Error messages and type names
- Source code locations (file:line:column)
- Nested error chains
§Overview
Unlike std::backtrace::Backtrace which captures the call stack,
error2::Backtrace tracks the logical error propagation path through
your application, showing where errors were created, converted, and propagated.
§Creation
Backtraces are typically created automatically by the #[derive(Error2)] macro:
use error2::prelude::*;
#[derive(Debug, Error2)]
#[error2(display("my error"))]
struct MyError {
backtrace: Backtrace,
}§Accessing Error Information
Use .error_message() to get a formatted error chain:
use regex::Regex;
if let Err(e) = operation() {
let msg = e.backtrace().error_message();
// Full error format with location tracking:
// TestError: test error
// at /path/to/file.rs:128:14
// std::io::error::Error: file not found
let re = Regex::new(concat!(
r"(?s)^.+TestError: test error",
r"\n at .+\.rs:\d+:\d+",
r"\nstd::io::error::Error: file not found$",
))
.unwrap();
assert!(re.is_match(msg.as_ref()));
}§Location Tracking
The backtrace automatically records the location where an error is first created. To track propagation through your call stack, you must manually call:
.attach()- Records the current location when an error passes through.attach_location()- Records a specific location
When converting errors:
.context()automatically captures where the conversion happens.build()/.fail()automatically captures where the root error is created
These methods use #[track_caller] to capture the caller’s location without manual intervention.
§Example with Nested Errors
use std::io;
use error2::prelude::*;
use regex::Regex;
#[derive(Debug, Error2)]
pub enum ConfigError {
#[error2(display("Failed to read: {path}"))]
Read {
path: String,
source: io::Error,
backtrace: Backtrace,
},
}
#[derive(Debug, Error2)]
pub enum AppError {
#[error2(display("Config error"))]
Config { source: ConfigError },
}
fn read_config() -> Result<String, ConfigError> {
std::fs::read_to_string("config.toml").context(Read2 {
path: "config.toml",
})
}
fn start_app() -> Result<String, AppError> {
read_config().context(Config2)
}
if let Err(e) = start_app() {
let msg = e.backtrace().error_message();
// Full error chain format:
// AppError: Config error
// at /path/to/file.rs:184:19
// ConfigError: Failed to read: config.toml
// at /path/to/file.rs:178:44
// std::io::error::Error: No such file or directory (os error 2)
let re = Regex::new(concat!(
r"(?s)^.+AppError: Config error",
r"\n at .+\.rs:\d+:\d+",
r"\n.+ConfigError: Failed to read: config\.toml",
r"\n at .+\.rs:\d+:\d+",
r"\nstd::io::error::Error: No such file or directory \(os error 2\)$",
))
.unwrap();
assert!(re.is_match(msg.as_ref()));
}Implementations§
Source§impl Backtrace
impl Backtrace
Sourcepub fn error_message(&self) -> Box<str>
pub fn error_message(&self) -> Box<str>
Returns a formatted string containing the complete error chain.
This method produces a human-readable representation of the entire error history, including all nested errors and their locations.
§Examples
use regex::Regex;
if let Err(e) = operation() {
let msg = e.backtrace().error_message();
// Full error format with location tracking:
// TestError: test error
// at /path/to/file.rs:197:14
// std::io::error::Error: file not found
let re = Regex::new(concat!(
r"(?s)^.+TestError: test error",
r"\n at .+\.rs:\d+:\d+",
r"\nstd::io::error::Error: file not found$",
))
.unwrap();
assert!(re.is_match(msg.as_ref()));
}Trait Implementations§
Source§impl Ord for Backtrace
impl Ord for Backtrace
Source§impl PartialOrd for Backtrace
impl PartialOrd for Backtrace
impl Eq for Backtrace
impl StructuralPartialEq for Backtrace
Auto Trait Implementations§
impl Freeze for Backtrace
impl RefUnwindSafe for Backtrace
impl Send for Backtrace
impl Sync for Backtrace
impl Unpin for Backtrace
impl UnwindSafe for Backtrace
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Comparable<K> for Q
impl<Q, K> Comparable<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
self with key and returns true if they are equal.