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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use crate::;
/// Convenience methods for creating root errors.
///
/// `RootError` provides `.build()` and `.fail()` for creating errors that
/// represent new error origins (not wrapping other errors).
///
/// # Root Error Pattern
///
/// A root error only has a `backtrace` field (no `source`):
///
/// ```
/// use error2::prelude::*;
///
/// #[derive(Debug, Error2)]
/// pub enum AppError {
/// #[error2(display("invalid ID: {id}"))]
/// InvalidId { id: i64, backtrace: Backtrace },
///
/// #[error2(display("channel closed"))]
/// ChannelClosed { backtrace: Backtrace },
/// }
/// ```
///
/// # Using .build()
///
/// Create an error instance:
///
/// ```
/// # use error2::prelude::*;
/// # #[derive(Debug, Error2)]
/// # pub enum AppError {
/// # #[error2(display("invalid ID: {id}"))]
/// # InvalidId { id: i64, backtrace: Backtrace },
/// # }
/// # fn validate(id: i64) -> Result<(), AppError> {
/// if id < 0 {
/// let error = InvalidId2 { id }.build();
/// // Use error...
/// }
/// # Ok(())
/// # }
/// ```
///
/// # Using .fail()
///
/// Create and return an error in one step:
///
/// ```
/// # use error2::prelude::*;
/// # #[derive(Debug, Error2)]
/// # pub enum AppError {
/// # #[error2(display("invalid ID: {id}"))]
/// # InvalidId { id: i64, backtrace: Backtrace },
/// # }
/// fn validate(id: i64) -> Result<(), AppError> {
/// if id < 0 {
/// return InvalidId2 { id }.fail();
/// }
/// Ok(())
/// }
/// ```
///
/// # Automatic Location Tracking
///
/// Both `.build()` and `.fail()` automatically capture the caller's
/// location using `#[track_caller]`, which is included in the backtrace.
///
/// ```
/// # use error2::prelude::*;
/// # #[derive(Debug, Error2)]
/// # pub enum AppError {
/// # #[error2(display("invalid ID: {id}"))]
/// # InvalidId { id: i64, backtrace: Backtrace },
/// # }
/// use regex::Regex;
///
/// let err = InvalidId2 { id: -1 }.build();
/// let msg = err.backtrace().error_message();
///
/// // Full error format with location tracking:
/// // AppError: invalid ID: -1
/// // at /path/to/file.rs:683:33
///
/// let re = Regex::new(concat!(
/// r"(?s)^.+AppError: invalid ID: -1",
/// r"\n at .+\.rs:\d+:\d+$",
/// ))
/// .unwrap();
/// assert!(re.is_match(msg.as_ref()));
/// ```