Skip to main content

anyerr/
lib.rs

1//! A trait object based error type for easy idiomatic error handling in Rust
2//! applications.
3//!
4//! It provides [`Error`], a trait object based error type, and the [`Result`]
5//! alias.
6//!
7//! # Details
8//!
9//! - Use `Result<T, anyerr::Error>`, or equivalently `anyerr::Result<T>`, as
10//!   the return type of any fallible function.
11//!
12//!   Within the function, use `?` to easily propagate any error that implements
13//!   the [`std::error::Error`] trait.
14//!
15//!   ```
16//!   # pub trait Deserialize {}
17//!   #
18//!   # mod serde_json {
19//!   #     use super::Deserialize;
20//!   #     use std::io;
21//!   #
22//!   #     pub fn from_str<T: Deserialize>(json: &str) -> io::Result<T> {
23//!   #         unimplemented!()
24//!   #     }
25//!   # }
26//!   #
27//!   # struct ClusterMap;
28//!   #
29//!   # impl Deserialize for ClusterMap {}
30//!   #
31//!   use anyerr::Result;
32//!
33//!   fn get_cluster_info() -> Result<ClusterMap> {
34//!       let config = std::fs::read_to_string("cluster.json")?;
35//!       let map: ClusterMap = serde_json::from_str(&config)?;
36//!       Ok(map)
37//!   }
38//!   #
39//!   # fn main() {}
40//!   ```
41//!
42//! - Attach context to help the person troubleshooting the error understand
43//!   where things went wrong. A low-level error like "No such file or
44//!   directory" can be annoying to debug without more context about what higher
45//!   level step the application was in the middle of.
46//!
47//!   ```
48//!   # struct It;
49//!   #
50//!   # impl It {
51//!   #     fn detach(&self) -> Result<()> {
52//!   #         unimplemented!()
53//!   #     }
54//!   # }
55//!   #
56//!   use anyerr::{Context, Result};
57//!
58//!   fn main() -> Result<()> {
59//!       # return Ok(());
60//!       #
61//!       # const _: &str = stringify! {
62//!       ...
63//!       # };
64//!       #
65//!       # let it = It;
66//!       # let path = "./path/to/instrs.json";
67//!       #
68//!       it.detach().context("Failed to detach the important thing")?;
69//!
70//!       let content = std::fs::read(path)
71//!           .with_context(|| format!("Failed to read instrs from {}", path))?;
72//!       #
73//!       # const _: &str = stringify! {
74//!       ...
75//!       # };
76//!       #
77//!       # Ok(())
78//!   }
79//!   ```
80//!
81//!   ```console
82//!   Error: Failed to read instrs from ./path/to/instrs.json
83//!
84//!   Caused by:
85//!       No such file or directory (os error 2)
86//!   ```
87//!
88//! - Downcasting is supported and can be by value, by shared reference, or by
89//!   mutable reference as needed.
90//!
91//!   ```
92//!   # use anyerr::anyhow;
93//!   # use std::fmt::{self, Display};
94//!   # use std::task::Poll;
95//!   #
96//!   # #[derive(Debug)]
97//!   # enum DataStoreError {
98//!   #     Censored(()),
99//!   # }
100//!   #
101//!   # impl Display for DataStoreError {
102//!   #     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
103//!   #         unimplemented!()
104//!   #     }
105//!   # }
106//!   #
107//!   # impl std::error::Error for DataStoreError {}
108//!   #
109//!   # const REDACTED_CONTENT: () = ();
110//!   #
111//!   # let error = anyhow!("...");
112//!   # let root_cause = &error;
113//!   #
114//!   # let ret =
115//!   // If the error was caused by redaction, then return a
116//!   // tombstone instead of the content.
117//!   match root_cause.downcast_ref::<DataStoreError>() {
118//!       Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
119//!       None => Err(error),
120//!   }
121//!   # ;
122//!   ```
123//!
124//! - A backtrace is captured and printed with the error if the underlying
125//!   error type does not already provide its own. In order to see backtraces,
126//!   they must be enabled through the environment variables described in
127//!   [`std::backtrace`]:
128//!
129//!   - If you want panics and errors to both have backtraces, set
130//!     `RUST_BACKTRACE=1`;
131//!   - If you want only errors to have backtraces, set `RUST_LIB_BACKTRACE=1`;
132//!   - If you want only panics to have backtraces, set `RUST_BACKTRACE=1` and
133//!     `RUST_LIB_BACKTRACE=0`.
134//!
135//!   [`std::backtrace`]: https://doc.rust-lang.org/std/backtrace/index.html#environment-variables
136//!
137//! - This crate works with any error type that has an impl of
138//!   `std::error::Error`, including ones defined in your crate. It does not
139//!   bundle a `derive(Error)` macro, but you can write the impls yourself or
140//!   use the standalone `thiserror` crate in this workspace.
141//!
142//!   ```
143//!   use thiserror::Error;
144//!
145//!   #[derive(Error, Debug)]
146//!   pub enum FormatError {
147//!       #[error("Invalid header (expected {expected:?}, got {found:?})")]
148//!       InvalidHeader {
149//!           expected: String,
150//!           found: String,
151//!       },
152//!       #[error("Missing attribute: {0}")]
153//!       MissingAttribute(String),
154//!   }
155//!   ```
156//!
157//! - One-off error messages can be constructed using the `anyhow!` macro, which
158//!   supports string interpolation and produces an `anyerr::Error`.
159//!
160//!   ```
161//!   # use anyerr::{anyhow, Result};
162//!   #
163//!   # fn demo() -> Result<()> {
164//!   #     let missing = "...";
165//!   return Err(anyhow!("Missing attribute: {}", missing));
166//!   #     Ok(())
167//!   # }
168//!   ```
169//!
170//!   A `bail!` macro is provided as a shorthand for the same early return.
171//!
172//!   ```
173//!   # use anyerr::{bail, Result};
174//!   #
175//!   # fn demo() -> Result<()> {
176//!   #     let missing = "...";
177//!   bail!("Missing attribute: {}", missing);
178//!   #     Ok(())
179//!   # }
180//!   ```
181//!
182//! # No-std support
183//!
184//! In no_std mode, almost all of the same API is available and works the same
185//! way. Disable the default enabled `std` feature to use it in no_std mode. A
186//! global allocator is required.
187//!
188//! Since the `?`-based error conversions would normally rely on the
189//! `std::error::Error` trait which is only available through std, no_std mode
190//! will require an explicit `.map_err(Error::msg)` when working with a
191//! non-anyerr error type inside a function that returns anyerr's error type.
192
193#![cfg_attr(error_generic_member_access, feature(error_generic_member_access))]
194#![cfg_attr(docsrs, feature(doc_cfg))]
195#![no_std]
196#![deny(dead_code, unused_imports, unused_mut)]
197#![deny(unsafe_op_in_unsafe_fn)]
198#![allow(
199    clippy::doc_markdown,
200    clippy::enum_glob_use,
201    clippy::explicit_auto_deref,
202    clippy::extra_unused_type_parameters,
203    clippy::incompatible_msrv,
204    clippy::let_underscore_untyped,
205    clippy::missing_errors_doc,
206    clippy::missing_panics_doc,
207    clippy::module_name_repetitions,
208    clippy::must_use_candidate,
209    clippy::needless_doctest_main,
210    clippy::new_ret_no_self,
211    clippy::redundant_else,
212    clippy::return_self_not_must_use,
213    clippy::struct_field_names,
214    clippy::unused_self,
215    clippy::used_underscore_binding,
216    clippy::wildcard_imports,
217    clippy::wrong_self_convention
218)]
219
220#[cfg(all(anyhow_nightly_testing, feature = "std", not(error_generic_member_access)))]
221compile_error!("Build script probe failed to compile.");
222
223extern crate alloc;
224
225#[cfg(feature = "std")]
226extern crate std;
227
228#[macro_use]
229mod backtrace;
230mod chain;
231mod context;
232mod ensure;
233mod error;
234mod fmt;
235mod kind;
236mod macros;
237mod ptr;
238mod wrapper;
239
240#[cfg(not(feature = "std"))]
241use core::fmt::Debug;
242use core::fmt::Display;
243#[cfg(feature = "std")]
244use std::error::Error as StdError;
245
246use crate::{error::ErrorImpl, ptr::Own};
247
248#[cfg(not(feature = "std"))]
249trait StdError: Debug + Display {
250    fn source(&self) -> Option<&(dyn StdError + 'static)> {
251        None
252    }
253}
254
255#[doc(no_inline)]
256pub use anyhow as format_err;
257
258/// The `Error` type, a wrapper around a dynamic error type.
259///
260/// `Error` works a lot like `Box<dyn std::error::Error>`, but with these
261/// differences:
262///
263/// - `Error` requires that the error is `Send`, `Sync`, and `'static`.
264/// - `Error` guarantees that a backtrace is available, even if the underlying
265///   error type does not provide one.
266/// - `Error` is represented as a narrow pointer &mdash; exactly one word in
267///   size instead of two.
268///
269/// <br>
270///
271/// # Display representations
272///
273/// When you print an error object using "{}" or to_string(), only the outermost
274/// underlying error or context is printed, not any of the lower level causes.
275/// This is exactly as if you had called the Display impl of the error from
276/// which you constructed your anyerr::Error.
277///
278/// ```console
279/// Failed to read instrs from ./path/to/instrs.json
280/// ```
281///
282/// To print causes as well using anyhow's default formatting of causes, use the
283/// alternate selector "{:#}".
284///
285/// ```console
286/// Failed to read instrs from ./path/to/instrs.json: No such file or directory (os error 2)
287/// ```
288///
289/// The Debug format "{:?}" includes your backtrace if one was captured. Note
290/// that this is the representation you get by default if you return an error
291/// from `fn main` instead of printing it explicitly yourself.
292///
293/// ```console
294/// Error: Failed to read instrs from ./path/to/instrs.json
295///
296/// Caused by:
297///     No such file or directory (os error 2)
298/// ```
299///
300/// and if there is a backtrace available:
301///
302/// ```console
303/// Error: Failed to read instrs from ./path/to/instrs.json
304///
305/// Caused by:
306///     No such file or directory (os error 2)
307///
308/// Stack backtrace:
309///    0: <E as anyerr::context::ext::StdError>::ext_context
310///              at /git/anyhow/src/backtrace.rs:26
311///    1: core::result::Result<T,E>::map_err
312///              at /git/rustc/src/libcore/result.rs:596
313///    2: anyerr::context::<impl anyerr::Context<T,E> for core::result::Result<T,E>>::with_context
314///              at /git/anyhow/src/context.rs:58
315///    3: testing::main
316///              at src/main.rs:5
317///    4: std::rt::lang_start
318///              at /git/rustc/src/libstd/rt.rs:61
319///    5: main
320///    6: __libc_start_main
321///    7: _start
322/// ```
323///
324/// To see a conventional struct-style Debug representation, use "{:#?}".
325///
326/// ```console
327/// Error {
328///     context: "Failed to read instrs from ./path/to/instrs.json",
329///     source: Os {
330///         code: 2,
331///         kind: NotFound,
332///         message: "No such file or directory",
333///     },
334/// }
335/// ```
336///
337/// If none of the built-in representations are appropriate and you would prefer
338/// to render the error and its cause chain yourself, it can be done something
339/// like this:
340///
341/// ```
342/// use anyerr::{Context, Result};
343///
344/// fn main() {
345///     if let Err(err) = try_main() {
346///         eprintln!("ERROR: {}", err);
347///         err.chain().skip(1).for_each(|cause| eprintln!("because: {}", cause));
348///         std::process::exit(1);
349///     }
350/// }
351///
352/// fn try_main() -> Result<()> {
353///     # const IGNORE: &str = stringify! {
354///     ...
355///     # };
356///     # Ok(())
357/// }
358/// ```
359#[repr(transparent)]
360pub struct Error {
361    inner: Own<ErrorImpl>,
362}
363
364/// Iterator of a chain of source errors.
365///
366/// This type is the iterator returned by [`Error::chain`].
367///
368/// # Example
369///
370/// ```
371/// use anyerr::Error;
372/// use std::io;
373///
374/// pub fn underlying_io_error_kind(error: &Error) -> Option<io::ErrorKind> {
375///     for cause in error.chain() {
376///         if let Some(io_error) = cause.downcast_ref::<io::Error>() {
377///             return Some(io_error.kind());
378///         }
379///     }
380///     None
381/// }
382/// ```
383#[cfg(feature = "std")]
384#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
385#[derive(Clone)]
386pub struct Chain<'a> {
387    state: crate::chain::ChainState<'a>,
388}
389
390/// `Result<T, Error>`
391///
392/// This is a reasonable return type to use throughout your application but also
393/// for `fn main`; if you do, failures will be printed along with any
394/// [context][Context] and a backtrace if one was captured.
395///
396/// `anyerr::Result` may be used with one *or* two type parameters.
397///
398/// ```rust
399/// use anyerr::Result;
400///
401/// # const IGNORE: &str = stringify! {
402/// fn demo1() -> Result<T> {...}
403///            // ^ equivalent to std::result::Result<T, anyerr::Error>
404///
405/// fn demo2() -> Result<T, OtherError> {...}
406///            // ^ equivalent to std::result::Result<T, OtherError>
407/// # };
408/// ```
409///
410/// # Example
411///
412/// ```
413/// # pub trait Deserialize {}
414/// #
415/// # mod serde_json {
416/// #     use super::Deserialize;
417/// #     use std::io;
418/// #
419/// #     pub fn from_str<T: Deserialize>(json: &str) -> io::Result<T> {
420/// #         unimplemented!()
421/// #     }
422/// # }
423/// #
424/// # #[derive(Debug)]
425/// # struct ClusterMap;
426/// #
427/// # impl Deserialize for ClusterMap {}
428/// #
429/// use anyerr::Result;
430///
431/// fn main() -> Result<()> {
432///     # return Ok(());
433///     let config = std::fs::read_to_string("cluster.json")?;
434///     let map: ClusterMap = serde_json::from_str(&config)?;
435///     println!("cluster info: {:#?}", map);
436///     Ok(())
437/// }
438/// ```
439pub type Result<T, E = Error> = core::result::Result<T, E>;
440
441/// Provides the `context` method for `Result`.
442///
443/// This trait is sealed and cannot be implemented for types outside of
444/// `anyhow`.
445///
446/// <br>
447///
448/// # Example
449///
450/// ```
451/// use anyerr::{Context, Result};
452/// use std::fs;
453/// use std::path::PathBuf;
454///
455/// pub struct ImportantThing {
456///     path: PathBuf,
457/// }
458///
459/// impl ImportantThing {
460///     # const IGNORE: &'static str = stringify! {
461///     pub fn detach(&mut self) -> Result<()> {...}
462///     # };
463///     # fn detach(&mut self) -> Result<()> {
464///     #     unimplemented!()
465///     # }
466/// }
467///
468/// pub fn do_it(mut it: ImportantThing) -> Result<Vec<u8>> {
469///     it.detach().context("Failed to detach the important thing")?;
470///
471///     let path = &it.path;
472///     let content = fs::read(path)
473///         .with_context(|| format!("Failed to read instrs from {}", path.display()))?;
474///
475///     Ok(content)
476/// }
477/// ```
478///
479/// When printed, the outermost context would be printed first and the lower
480/// level underlying causes would be enumerated below.
481///
482/// ```console
483/// Error: Failed to read instrs from ./path/to/instrs.json
484///
485/// Caused by:
486///     No such file or directory (os error 2)
487/// ```
488///
489/// Refer to the [Display representations] documentation for other forms in
490/// which this context chain can be rendered.
491///
492/// [Display representations]: Error#display-representations
493///
494/// <br>
495///
496/// # Effect on downcasting
497///
498/// After attaching context of type `C` onto an error of type `E`, the resulting
499/// `anyerr::Error` may be downcast to `C` **or** to `E`.
500///
501/// That is, in codebases that rely on downcasting, Anyhow's context supports
502/// both of the following use cases:
503///
504///   - **Attaching context whose type is insignificant onto errors whose type
505///     is used in downcasts.**
506///
507///     In other error libraries whose context is not designed this way, it can
508///     be risky to introduce context to existing code because new context might
509///     break existing working downcasts. In Anyhow, any downcast that worked
510///     before adding context will continue to work after you add a context, so
511///     you should freely add human-readable context to errors wherever it would
512///     be helpful.
513///
514///     ```
515///     # use anyerr::bail;
516///     # use thiserror::Error;
517///     #
518///     # #[derive(Error, Debug)]
519///     # #[error("???")]
520///     # struct SuspiciousError;
521///     #
522///     # fn helper() -> Result<()> {
523///     #     bail!(SuspiciousError);
524///     # }
525///     #
526///     use anyerr::{Context, Result};
527///
528///     fn do_it() -> Result<()> {
529///         helper().context("Failed to complete the work")?;
530///         # const IGNORE: &str = stringify! {
531///         ...
532///         # };
533///         # unreachable!()
534///     }
535///
536///     fn main() {
537///         let err = do_it().unwrap_err();
538///         if let Some(e) = err.downcast_ref::<SuspiciousError>() {
539///             // If helper() returned SuspiciousError, this downcast will
540///             // correctly succeed even with the context in between.
541///             # return;
542///         }
543///         # panic!("expected downcast to succeed");
544///     }
545///     ```
546///
547///   - **Attaching context whose type is used in downcasts onto errors whose
548///     type is insignificant.**
549///
550///     Some codebases prefer to use machine-readable context to categorize
551///     lower level errors in a way that will be actionable to higher levels of
552///     the application.
553///
554///     ```
555///     # use anyerr::bail;
556///     # use thiserror::Error;
557///     #
558///     # #[derive(Error, Debug)]
559///     # #[error("???")]
560///     # struct HelperFailed;
561///     #
562///     # fn helper() -> Result<()> {
563///     #     bail!("no such file or directory");
564///     # }
565///     #
566///     use anyerr::{Context, Result};
567///
568///     fn do_it() -> Result<()> {
569///         helper().context(HelperFailed)?;
570///         # const IGNORE: &str = stringify! {
571///         ...
572///         # };
573///         # unreachable!()
574///     }
575///
576///     fn main() {
577///         let err = do_it().unwrap_err();
578///         if let Some(e) = err.downcast_ref::<HelperFailed>() {
579///             // If helper failed, this downcast will succeed because
580///             // HelperFailed is the context that has been attached to
581///             // that error.
582///             # return;
583///         }
584///         # panic!("expected downcast to succeed");
585///     }
586///     ```
587pub trait Context<T, E>: context::private::Sealed {
588    /// Wrap the error value with additional context.
589    fn context<C>(self, context: C) -> Result<T, Error>
590    where
591        C: Display + Send + Sync + 'static;
592
593    /// Wrap the error value with additional context that is evaluated lazily
594    /// only once an error does occur.
595    fn with_context<C, F>(self, f: F) -> Result<T, Error>
596    where
597        C: Display + Send + Sync + 'static,
598        F: FnOnce() -> C;
599}
600
601/// Equivalent to Ok::<_, anyerr::Error>(value).
602///
603/// This simplifies creation of an anyerr::Result in places where type inference
604/// cannot deduce the `E` type of the result &mdash; without needing to write
605/// `Ok::<_, anyerr::Error>(value)`.
606///
607/// One might think that `anyerr::Result::Ok(value)` would work in such cases
608/// but it does not.
609///
610/// ```console
611/// error[E0282]: type annotations needed for `std::result::Result<i32, E>`
612///   --> src/main.rs:11:13
613///    |
614/// 11 |     let _ = anyerr::Result::Ok(1);
615///    |         -   ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `E` declared on the enum `Result`
616///    |         |
617///    |         consider giving this pattern the explicit type `std::result::Result<i32, E>`, where the type parameter `E` is specified
618/// ```
619#[allow(non_snake_case)]
620pub fn Ok<T>(t: T) -> Result<T> {
621    Result::Ok(t)
622}
623
624// Not public API. Referenced by macro-generated code.
625#[doc(hidden)]
626pub mod __private {
627    use alloc::fmt;
628    #[doc(hidden)]
629    pub use alloc::format;
630    use core::fmt::Arguments;
631    #[doc(hidden)]
632    pub use core::result::Result::Err;
633    #[doc(hidden)]
634    pub use core::{concat, format_args, stringify};
635
636    use self::not::Bool;
637    use crate::Error;
638    #[doc(hidden)]
639    pub use crate::ensure::{BothDebug, NotBothDebug};
640
641    #[doc(hidden)]
642    pub mod kind {
643        #[cfg(feature = "std")]
644        #[doc(hidden)]
645        pub use crate::kind::BoxedKind;
646        #[doc(hidden)]
647        pub use crate::kind::{AdhocKind, TraitKind};
648    }
649
650    #[doc(hidden)]
651    #[inline]
652    #[cold]
653    pub fn format_err(args: Arguments) -> Error {
654        let fmt_arguments_as_str = args.as_str();
655
656        if let Some(message) = fmt_arguments_as_str {
657            // anyhow!("literal"), can downcast to &'static str
658            Error::msg(message)
659        } else {
660            // anyhow!("interpolate {var}"), can downcast to String
661            Error::msg(fmt::format(args))
662        }
663    }
664
665    #[doc(hidden)]
666    #[inline]
667    #[cold]
668    #[must_use]
669    pub fn must_use(error: Error) -> Error {
670        error
671    }
672
673    #[doc(hidden)]
674    #[inline]
675    pub fn not(cond: impl Bool) -> bool {
676        cond.not()
677    }
678
679    mod not {
680        #[doc(hidden)]
681        pub trait Bool {
682            fn not(self) -> bool;
683        }
684
685        impl Bool for bool {
686            #[inline]
687            fn not(self) -> bool {
688                !self
689            }
690        }
691
692        impl Bool for &bool {
693            #[inline]
694            fn not(self) -> bool {
695                !*self
696            }
697        }
698    }
699}