1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use crate::;
/// Record error propagation locations for detailed backtraces.
///
/// The `Attach` trait provides the `.attach()` method which records where
/// an error was propagated through your code, creating a complete call chain.
///
/// # Basic Usage
///
/// Use `.attach()` when propagating errors with `?`:
///
/// ```
/// use std::io;
///
/// use error2::prelude::*;
///
/// #[derive(Debug, Error2)]
/// #[error2(display("io error"))]
/// struct IoError {
/// source: io::Error,
/// backtrace: Backtrace,
/// }
///
/// fn inner() -> Result<String, IoError> {
/// std::fs::read_to_string("file.txt").context(IoError2)
/// }
///
/// fn outer() -> Result<String, IoError> {
/// let result = inner().attach()?; // Records this location in backtrace
/// Ok(result)
/// }
/// ```
///
/// # Why Use Attach?
///
/// Without `.attach()`, the backtrace only shows where the error was created.
/// With `.attach()`, it shows every point the error passed through.
///
/// ```
/// # use error2::prelude::*;
/// # use std::io;
/// # #[derive(Debug, Error2)]
/// # #[error2(display("io error"))]
/// # struct IoError { source: io::Error, backtrace: Backtrace }
/// # fn inner() -> Result<String, IoError> {
/// # let err = io::Error::new(io::ErrorKind::NotFound, "file not found");
/// # Err(err).context(IoError2)
/// # }
/// # fn outer() -> Result<String, IoError> {
/// # inner().attach()
/// # }
/// use regex::Regex;
///
/// if let Err(e) = outer() {
/// let msg = e.backtrace().error_message();
///
/// // Full error format with multiple locations:
/// // IoError: io error
/// // at /path/to/file.rs:39:14
/// // at /path/to/file.rs:42:13
/// // std::io::error::Error: file not found
///
/// let re = Regex::new(concat!(
/// r"(?s)^.+IoError: io error",
/// r"\n at .+\.rs:\d+:\d+",
/// r"\n at .+\.rs:\d+:\d+",
/// r"\nstd::io::error::Error: file not found$",
/// ))
/// .unwrap();
/// assert!(re.is_match(msg.as_ref()));
/// }
/// ```