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