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