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 std::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 containing a `#[from]` |
102 | //! attribute. |
103 | //! |
104 | //! Note that the variant must not contain any other fields beyond the source |
105 | //! error and possibly a backtrace. A backtrace is captured from within the |
106 | //! `From` impl if there is a field for it. |
107 | //! |
108 | //! ```rust |
109 | //! # const IGNORE: &str = stringify! { |
110 | //! #[derive(Error, Debug)] |
111 | //! pub enum MyError { |
112 | //! Io { |
113 | //! #[from] |
114 | //! source: io::Error, |
115 | //! backtrace: Backtrace, |
116 | //! }, |
117 | //! } |
118 | //! # }; |
119 | //! ``` |
120 | //! |
121 | //! - The Error trait's `source()` method is implemented to return whichever |
122 | //! field has a `#[source]` attribute or is named `source`, if any. This is |
123 | //! for identifying the underlying lower level error that caused your error. |
124 | //! |
125 | //! The `#[from]` attribute always implies that the same field is `#[source]`, |
126 | //! so you don't ever need to specify both attributes. |
127 | //! |
128 | //! Any error type that implements `std::error::Error` or dereferences to `dyn |
129 | //! std::error::Error` will work as a source. |
130 | //! |
131 | //! ```rust |
132 | //! # use std::fmt::{self, Display}; |
133 | //! # use thiserror::Error; |
134 | //! # |
135 | //! #[derive(Error, Debug)] |
136 | //! pub struct MyError { |
137 | //! msg: String, |
138 | //! #[source] // optional if field name is `source` |
139 | //! source: anyhow::Error, |
140 | //! } |
141 | //! # |
142 | //! # impl Display for MyError { |
143 | //! # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
144 | //! # unimplemented!() |
145 | //! # } |
146 | //! # } |
147 | //! ``` |
148 | //! |
149 | //! - The Error trait's `provide()` method is implemented to provide whichever |
150 | //! field has a type named `Backtrace`, if any, as a |
151 | //! `std::backtrace::Backtrace`. |
152 | //! |
153 | //! ```rust |
154 | //! # const IGNORE: &str = stringify! { |
155 | //! use std::backtrace::Backtrace; |
156 | //! |
157 | //! #[derive(Error, Debug)] |
158 | //! pub struct MyError { |
159 | //! msg: String, |
160 | //! backtrace: Backtrace, // automatically detected |
161 | //! } |
162 | //! # }; |
163 | //! ``` |
164 | //! |
165 | //! - If a field is both a source (named `source`, or has `#[source]` or |
166 | //! `#[from]` attribute) *and* is marked `#[backtrace]`, then the Error |
167 | //! trait's `provide()` method is forwarded to the source's `provide` so that |
168 | //! both layers of the error share the same backtrace. |
169 | //! |
170 | //! ```rust |
171 | //! # const IGNORE: &str = stringify! { |
172 | //! #[derive(Error, Debug)] |
173 | //! pub enum MyError { |
174 | //! Io { |
175 | //! #[backtrace] |
176 | //! source: io::Error, |
177 | //! }, |
178 | //! } |
179 | //! # }; |
180 | //! ``` |
181 | //! |
182 | //! - Errors may use `error(transparent)` to forward the source and Display |
183 | //! methods straight through to an underlying error without adding an |
184 | //! additional message. This would be appropriate for enums that need an |
185 | //! "anything else" variant. |
186 | //! |
187 | //! ``` |
188 | //! # use thiserror::Error; |
189 | //! # |
190 | //! #[derive(Error, Debug)] |
191 | //! pub enum MyError { |
192 | //! # /* |
193 | //! ... |
194 | //! # */ |
195 | //! |
196 | //! #[error(transparent)] |
197 | //! Other(#[from] anyhow::Error), // source and Display delegate to anyhow::Error |
198 | //! } |
199 | //! ``` |
200 | //! |
201 | //! Another use case is hiding implementation details of an error |
202 | //! representation behind an opaque error type, so that the representation is |
203 | //! able to evolve without breaking the crate's public API. |
204 | //! |
205 | //! ``` |
206 | //! # use thiserror::Error; |
207 | //! # |
208 | //! // PublicError is public, but opaque and easy to keep compatible. |
209 | //! #[derive(Error, Debug)] |
210 | //! #[error(transparent)] |
211 | //! pub struct PublicError(#[from] ErrorRepr); |
212 | //! |
213 | //! impl PublicError { |
214 | //! // Accessors for anything we do want to expose publicly. |
215 | //! } |
216 | //! |
217 | //! // Private and free to change across minor version of the crate. |
218 | //! #[derive(Error, Debug)] |
219 | //! enum ErrorRepr { |
220 | //! # /* |
221 | //! ... |
222 | //! # */ |
223 | //! } |
224 | //! ``` |
225 | //! |
226 | //! - See also the [`anyhow`] library for a convenient single error type to use |
227 | //! in application code. |
228 | //! |
229 | //! [`anyhow`]: https://github.com/dtolnay/anyhow |
230 | |
231 | #![doc (html_root_url = "https://docs.rs/thiserror/1.0.58" )] |
232 | #![allow ( |
233 | clippy::module_name_repetitions, |
234 | clippy::needless_lifetimes, |
235 | clippy::return_self_not_must_use, |
236 | clippy::wildcard_imports |
237 | )] |
238 | #![cfg_attr (error_generic_member_access, feature(error_generic_member_access))] |
239 | |
240 | #[cfg (all(thiserror_nightly_testing, not(error_generic_member_access)))] |
241 | compile_error!("Build script probe failed to compile." ); |
242 | |
243 | mod aserror; |
244 | mod display; |
245 | #[cfg (error_generic_member_access)] |
246 | mod provide; |
247 | |
248 | pub use thiserror_impl::*; |
249 | |
250 | // Not public API. |
251 | #[doc (hidden)] |
252 | pub mod __private { |
253 | #[doc (hidden)] |
254 | pub use crate::aserror::AsDynError; |
255 | #[doc (hidden)] |
256 | pub use crate::display::AsDisplay; |
257 | #[cfg (error_generic_member_access)] |
258 | #[doc (hidden)] |
259 | pub use crate::provide::ThiserrorProvide; |
260 | } |
261 | |