1 | //! [![github]](https://github.com/dtolnay/thiserror) [![crates-io]](https://crates.io/crates/thiserror) [![docs-rs]](https://docs.rs/thiserror) |
2 | //! |
3 | //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github |
4 | //! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust |
5 | //! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs |
6 | //! |
7 | //! <br> |
8 | //! |
9 | //! This library provides a convenient derive macro for the standard library's |
10 | //! [`std::error::Error`] trait. |
11 | //! |
12 | //! [`std::error::Error`]: https://doc.rust-lang.org/std/error/trait.Error.html |
13 | //! |
14 | //! <br> |
15 | //! |
16 | //! # Example |
17 | //! |
18 | //! ```rust |
19 | //! # use std::io; |
20 | //! use thiserror::Error; |
21 | //! |
22 | //! #[derive(Error, Debug)] |
23 | //! pub enum DataStoreError { |
24 | //! #[error("data store disconnected" )] |
25 | //! Disconnect(#[from] io::Error), |
26 | //! #[error("the data for key `{0}` is not available" )] |
27 | //! Redaction(String), |
28 | //! #[error("invalid header (expected {expected:?}, found {found:?})" )] |
29 | //! InvalidHeader { |
30 | //! expected: String, |
31 | //! found: String, |
32 | //! }, |
33 | //! #[error("unknown data store error" )] |
34 | //! Unknown, |
35 | //! } |
36 | //! ``` |
37 | //! |
38 | //! <br> |
39 | //! |
40 | //! # Details |
41 | //! |
42 | //! - Thiserror deliberately does not appear in your public API. You get the |
43 | //! same thing as if you had written an implementation of `std::error::Error` |
44 | //! by hand, and switching from handwritten impls to thiserror or vice versa |
45 | //! is not a breaking change. |
46 | //! |
47 | //! - Errors may be enums, structs with named fields, tuple structs, or unit |
48 | //! structs. |
49 | //! |
50 | //! - A `Display` impl is generated for your error if you provide |
51 | //! `#[error("...")]` messages on the struct or each variant of your enum, as |
52 | //! shown above in the example. |
53 | //! |
54 | //! The messages support a shorthand for interpolating fields from the error. |
55 | //! |
56 | //! - `#[error("{var}")]` ⟶ `write!("{}", self.var)` |
57 | //! - `#[error("{0}")]` ⟶ `write!("{}", self.0)` |
58 | //! - `#[error("{var:?}")]` ⟶ `write!("{:?}", self.var)` |
59 | //! - `#[error("{0:?}")]` ⟶ `write!("{:?}", self.0)` |
60 | //! |
61 | //! These shorthands can be used together with any additional format args, |
62 | //! which may be arbitrary expressions. For example: |
63 | //! |
64 | //! ```rust |
65 | //! # use core::i32; |
66 | //! # use thiserror::Error; |
67 | //! # |
68 | //! #[derive(Error, Debug)] |
69 | //! pub enum Error { |
70 | //! #[error("invalid rdo_lookahead_frames {0} (expected < {})" , i32::MAX)] |
71 | //! InvalidLookahead(u32), |
72 | //! } |
73 | //! ``` |
74 | //! |
75 | //! If one of the additional expression arguments needs to refer to a field of |
76 | //! the struct or enum, then refer to named fields as `.var` and tuple fields |
77 | //! as `.0`. |
78 | //! |
79 | //! ```rust |
80 | //! # use thiserror::Error; |
81 | //! # |
82 | //! # fn first_char(s: &String) -> char { |
83 | //! # s.chars().next().unwrap() |
84 | //! # } |
85 | //! # |
86 | //! # #[derive(Debug)] |
87 | //! # struct Limits { |
88 | //! # lo: usize, |
89 | //! # hi: usize, |
90 | //! # } |
91 | //! # |
92 | //! #[derive(Error, Debug)] |
93 | //! pub enum Error { |
94 | //! #[error("first letter must be lowercase but was {:?}" , first_char(.0))] |
95 | //! WrongCase(String), |
96 | //! #[error("invalid index {idx}, expected at least {} and at most {}" , .limits.lo, .limits.hi)] |
97 | //! OutOfBounds { idx: usize, limits: Limits }, |
98 | //! } |
99 | //! ``` |
100 | //! |
101 | //! - A `From` impl is generated for each variant that contains a `#[from]` |
102 | //! attribute. |
103 | //! |
104 | //! The variant using `#[from]` must not contain any other fields beyond the |
105 | //! source error (and possibly a backtrace — see below). Usually |
106 | //! `#[from]` fields are unnamed, but `#[from]` is allowed on a named field |
107 | //! too. |
108 | //! |
109 | //! ```rust |
110 | //! # use core::fmt::{self, Display}; |
111 | //! # use std::io; |
112 | //! # use thiserror::Error; |
113 | //! # |
114 | //! # mod globset { |
115 | //! # #[derive(thiserror::Error, Debug)] |
116 | //! # #[error("..." )] |
117 | //! # pub struct Error; |
118 | //! # } |
119 | //! # |
120 | //! #[derive(Error, Debug)] |
121 | //! pub enum MyError { |
122 | //! Io(#[from] io::Error), |
123 | //! Glob(#[from] globset::Error), |
124 | //! } |
125 | //! # |
126 | //! # impl Display for MyError { |
127 | //! # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
128 | //! # unimplemented!() |
129 | //! # } |
130 | //! # } |
131 | //! ``` |
132 | //! |
133 | //! - The Error trait's `source()` method is implemented to return whichever |
134 | //! field has a `#[source]` attribute or is named `source`, if any. This is |
135 | //! for identifying the underlying lower level error that caused your error. |
136 | //! |
137 | //! The `#[from]` attribute always implies that the same field is `#[source]`, |
138 | //! so you don't ever need to specify both attributes. |
139 | //! |
140 | //! Any error type that implements `std::error::Error` or dereferences to `dyn |
141 | //! std::error::Error` will work as a source. |
142 | //! |
143 | //! ```rust |
144 | //! # use core::fmt::{self, Display}; |
145 | //! # use thiserror::Error; |
146 | //! # |
147 | //! #[derive(Error, Debug)] |
148 | //! pub struct MyError { |
149 | //! msg: String, |
150 | //! #[source] // optional if field name is `source` |
151 | //! source: anyhow::Error, |
152 | //! } |
153 | //! # |
154 | //! # impl Display for MyError { |
155 | //! # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
156 | //! # unimplemented!() |
157 | //! # } |
158 | //! # } |
159 | //! ``` |
160 | //! |
161 | //! - The Error trait's `provide()` method is implemented to provide whichever |
162 | //! field has a type named `Backtrace`, if any, as a |
163 | //! `std::backtrace::Backtrace`. Using `Backtrace` in errors requires a |
164 | //! nightly compiler with Rust version 1.73 or newer. |
165 | //! |
166 | //! ```rust |
167 | //! # const IGNORE: &str = stringify! { |
168 | //! use std::backtrace::Backtrace; |
169 | //! |
170 | //! #[derive(Error, Debug)] |
171 | //! pub struct MyError { |
172 | //! msg: String, |
173 | //! backtrace: Backtrace, // automatically detected |
174 | //! } |
175 | //! # }; |
176 | //! ``` |
177 | //! |
178 | //! - If a field is both a source (named `source`, or has `#[source]` or |
179 | //! `#[from]` attribute) *and* is marked `#[backtrace]`, then the Error |
180 | //! trait's `provide()` method is forwarded to the source's `provide` so that |
181 | //! both layers of the error share the same backtrace. The `#[backtrace]` |
182 | //! attribute requires a nightly compiler with Rust version 1.73 or newer. |
183 | //! |
184 | //! ```rust |
185 | //! # const IGNORE: &str = stringify! { |
186 | //! #[derive(Error, Debug)] |
187 | //! pub enum MyError { |
188 | //! Io { |
189 | //! #[backtrace] |
190 | //! source: io::Error, |
191 | //! }, |
192 | //! } |
193 | //! # }; |
194 | //! ``` |
195 | //! |
196 | //! - For variants that use `#[from]` and also contain a `Backtrace` field, a |
197 | //! backtrace is captured from within the `From` impl. |
198 | //! |
199 | //! ```rust |
200 | //! # const IGNORE: &str = stringify! { |
201 | //! #[derive(Error, Debug)] |
202 | //! pub enum MyError { |
203 | //! Io { |
204 | //! #[from] |
205 | //! source: io::Error, |
206 | //! backtrace: Backtrace, |
207 | //! }, |
208 | //! } |
209 | //! # }; |
210 | //! ``` |
211 | //! |
212 | //! - Errors may use `error(transparent)` to forward the source and Display |
213 | //! methods straight through to an underlying error without adding an |
214 | //! additional message. This would be appropriate for enums that need an |
215 | //! "anything else" variant. |
216 | //! |
217 | //! ``` |
218 | //! # use thiserror::Error; |
219 | //! # |
220 | //! #[derive(Error, Debug)] |
221 | //! pub enum MyError { |
222 | //! # /* |
223 | //! ... |
224 | //! # */ |
225 | //! |
226 | //! #[error(transparent)] |
227 | //! Other(#[from] anyhow::Error), // source and Display delegate to anyhow::Error |
228 | //! } |
229 | //! ``` |
230 | //! |
231 | //! Another use case is hiding implementation details of an error |
232 | //! representation behind an opaque error type, so that the representation is |
233 | //! able to evolve without breaking the crate's public API. |
234 | //! |
235 | //! ``` |
236 | //! # use thiserror::Error; |
237 | //! # |
238 | //! // PublicError is public, but opaque and easy to keep compatible. |
239 | //! #[derive(Error, Debug)] |
240 | //! #[error(transparent)] |
241 | //! pub struct PublicError(#[from] ErrorRepr); |
242 | //! |
243 | //! impl PublicError { |
244 | //! // Accessors for anything we do want to expose publicly. |
245 | //! } |
246 | //! |
247 | //! // Private and free to change across minor version of the crate. |
248 | //! #[derive(Error, Debug)] |
249 | //! enum ErrorRepr { |
250 | //! # /* |
251 | //! ... |
252 | //! # */ |
253 | //! } |
254 | //! ``` |
255 | //! |
256 | //! - See also the [`anyhow`] library for a convenient single error type to use |
257 | //! in application code. |
258 | //! |
259 | //! [`anyhow`]: https://github.com/dtolnay/anyhow |
260 | |
261 | #![doc (html_root_url = "https://docs.rs/thiserror/1.0.69" )] |
262 | #![allow ( |
263 | clippy::module_name_repetitions, |
264 | clippy::needless_lifetimes, |
265 | clippy::return_self_not_must_use, |
266 | clippy::wildcard_imports |
267 | )] |
268 | #![cfg_attr (error_generic_member_access, feature(error_generic_member_access))] |
269 | |
270 | #[cfg (all(thiserror_nightly_testing, not(error_generic_member_access)))] |
271 | compile_error!("Build script probe failed to compile." ); |
272 | |
273 | mod aserror; |
274 | mod display; |
275 | #[cfg (error_generic_member_access)] |
276 | mod provide; |
277 | |
278 | pub use thiserror_impl::*; |
279 | |
280 | // Not public API. |
281 | #[doc (hidden)] |
282 | pub mod __private { |
283 | #[doc (hidden)] |
284 | pub use crate::aserror::AsDynError; |
285 | #[doc (hidden)] |
286 | pub use crate::display::AsDisplay; |
287 | #[cfg (error_generic_member_access)] |
288 | #[doc (hidden)] |
289 | pub use crate::provide::ThiserrorProvide; |
290 | } |
291 | |