snafu/
lib.rs

1#![deny(missing_docs)]
2#![cfg_attr(not(any(feature = "std", test)), no_std)]
3#![cfg_attr(feature = "unstable-backtraces-impl-std", feature(backtrace))]
4#![cfg_attr(feature = "unstable-core-error", feature(error_in_core))]
5#![cfg_attr(
6    feature = "unstable-provider-api",
7    feature(error_generic_member_access, provide_any)
8)]
9#![cfg_attr(feature = "unstable-try-trait", feature(try_trait_v2))]
10
11//! # SNAFU
12//!
13//! SNAFU is a library to easily generate errors and add information
14//! to underlying errors, especially when the same underlying error
15//! type can occur in different contexts.
16//!
17//! For detailed information, please see the [`Snafu`][] macro and the
18//! [user's guide](guide).
19//!
20//! ## Features
21//!
22//! - [Turnkey errors based on strings](Whatever)
23//! - [Custom error types](Snafu)
24//!   - Including a conversion path from turnkey errors
25//! - [Backtraces](Backtrace)
26//! - Extension traits for
27//!   - [`Results`](ResultExt)
28//!   - [`Options`](OptionExt)
29#![cfg_attr(feature = "futures", doc = "   - [`Futures`](futures::TryFutureExt)")]
30#![cfg_attr(feature = "futures", doc = "   - [`Streams`](futures::TryStreamExt)")]
31//! - Suitable for libraries and applications
32//! - `no_std` compatibility
33//! - Generic types and lifetimes
34//!
35//! ## Quick start
36//!
37//! If you want to report errors without hassle, start with the
38//! [`Whatever`][] type and the [`whatever!`][] macro:
39//!
40//! ```rust
41//! use snafu::{prelude::*, Whatever};
42//!
43//! fn is_valid_id(id: u16) -> Result<(), Whatever> {
44//!     if id < 10 {
45//!         whatever!("ID may not be less than 10, but it was {}", id);
46//!     }
47//!     Ok(())
48//! }
49//! ```
50//!
51//! You can also use it to wrap any other error:
52//!
53//! ```rust
54//! use snafu::{prelude::*, Whatever};
55//!
56//! fn read_config_file(path: &str) -> Result<String, Whatever> {
57//!     std::fs::read_to_string(path)
58//!         .with_whatever_context(|_| format!("Could not read file {}", path))
59//! }
60//! ```
61//!
62//! [`Whatever`][] allows for a short message and tracks a
63//! [`Backtrace`][] for every error:
64//!
65//! ```rust
66//! use snafu::{prelude::*, ErrorCompat, Whatever};
67//!
68//! fn main() {
69//! # fn returns_an_error() -> Result<(), Whatever> { Ok(()) }
70//!     if let Err(e) = returns_an_error() {
71//!         eprintln!("An error occurred: {}", e);
72//!         if let Some(bt) = ErrorCompat::backtrace(&e) {
73//! #           #[cfg(not(feature = "backtraces-impl-backtrace-crate"))]
74//!             eprintln!("{}", bt);
75//!         }
76//!     }
77//! }
78//! ```
79//!
80//! ## Custom error types
81//!
82//! Many projects will hit limitations of the `Whatever` type. When
83//! that occurs, it's time to create your own error type by deriving
84//! [`Snafu`][]!
85//!
86//! ### Struct style
87//!
88//! SNAFU will read your error struct definition and create a *context
89//! selector* type (called `InvalidIdSnafu` in this example). These
90//! context selectors are used with the [`ensure!`][] macro to provide
91//! ergonomic error creation:
92//!
93//! ```rust
94//! use snafu::prelude::*;
95//!
96//! #[derive(Debug, Snafu)]
97//! #[snafu(display("ID may not be less than 10, but it was {id}"))]
98//! struct InvalidIdError {
99//!     id: u16,
100//! }
101//!
102//! fn is_valid_id(id: u16) -> Result<(), InvalidIdError> {
103//!     ensure!(id >= 10, InvalidIdSnafu { id });
104//!     Ok(())
105//! }
106//! ```
107//!
108//! If you add a `source` field to your error, you can then wrap an
109//! underlying error using the [`context`](ResultExt::context)
110//! extension method:
111//!
112//! ```rust
113//! use snafu::prelude::*;
114//!
115//! #[derive(Debug, Snafu)]
116//! #[snafu(display("Could not read file {path}"))]
117//! struct ConfigFileError {
118//!     source: std::io::Error,
119//!     path: String,
120//! }
121//!
122//! fn read_config_file(path: &str) -> Result<String, ConfigFileError> {
123//!     std::fs::read_to_string(path).context(ConfigFileSnafu { path })
124//! }
125//! ```
126//!
127//! ### Enum style
128//!
129//! While error structs are good for constrained cases, they don't
130//! allow for reporting multiple possible kinds of errors at one
131//! time. Error enums solve that problem.
132//!
133//! SNAFU will read your error enum definition and create a *context
134//! selector* type for each variant (called `InvalidIdSnafu` in this
135//! example). These context selectors are used with the [`ensure!`][]
136//! macro to provide ergonomic error creation:
137//!
138//! ```rust
139//! use snafu::prelude::*;
140//!
141//! #[derive(Debug, Snafu)]
142//! enum Error {
143//!     #[snafu(display("ID may not be less than 10, but it was {id}"))]
144//!     InvalidId { id: u16 },
145//! }
146//!
147//! fn is_valid_id(id: u16) -> Result<(), Error> {
148//!     ensure!(id >= 10, InvalidIdSnafu { id });
149//!     Ok(())
150//! }
151//! ```
152//!
153//! If you add a `source` field to a variant, you can then wrap an
154//! underlying error using the [`context`](ResultExt::context)
155//! extension method:
156//!
157//! ```rust
158//! use snafu::prelude::*;
159//!
160//! #[derive(Debug, Snafu)]
161//! enum Error {
162//!     #[snafu(display("Could not read file {path}"))]
163//!     ConfigFile {
164//!         source: std::io::Error,
165//!         path: String,
166//!     },
167//! }
168//!
169//! fn read_config_file(path: &str) -> Result<String, Error> {
170//!     std::fs::read_to_string(path).context(ConfigFileSnafu { path })
171//! }
172//! ```
173//!
174//! You can combine the power of the [`whatever!`][] macro with an
175//! enum error type. This is great if you started out with
176//! [`Whatever`][] and are moving to a custom error type:
177//!
178//! ```rust
179//! use snafu::prelude::*;
180//!
181//! #[derive(Debug, Snafu)]
182//! enum Error {
183//!     #[snafu(display("ID may not be less than 10, but it was {id}"))]
184//!     InvalidId { id: u16 },
185//!
186//!     #[snafu(whatever, display("{message}"))]
187//!     Whatever {
188//!         message: String,
189//!         #[snafu(source(from(Box<dyn std::error::Error>, Some)))]
190//!         source: Option<Box<dyn std::error::Error>>,
191//!     },
192//! }
193//!
194//! fn is_valid_id(id: u16) -> Result<(), Error> {
195//!     ensure!(id >= 10, InvalidIdSnafu { id });
196//!     whatever!("Just kidding... this function always fails!");
197//!     Ok(())
198//! }
199//! ```
200//!
201//! You may wish to make the type `Send` and/or `Sync`, allowing
202//! your error type to be used in multithreaded programs, by changing
203//! `dyn std::error::Error` to `dyn std::error::Error + Send + Sync`.
204//!
205//! ## Next steps
206//!
207//! Read the documentation for the [`Snafu`][] macro to see all of the
208//! capabilities, then read the [user's guide](guide) for deeper
209//! understanding.
210
211use core::fmt;
212
213pub mod prelude {
214    //! Traits and macros used by most projects. Add `use
215    //! snafu::prelude::*` to your code to quickly get started with
216    //! SNAFU.
217
218    pub use crate::{ensure, OptionExt as _, ResultExt as _};
219
220    // https://github.com/rust-lang/rust/issues/89020
221    doc_comment::doc_comment! {
222        include_str!("Snafu.md"),
223        pub use snafu_derive::Snafu;
224    }
225
226    #[cfg(any(feature = "std", test))]
227    pub use crate::{ensure_whatever, whatever};
228
229    #[cfg(feature = "futures")]
230    pub use crate::futures::{TryFutureExt as _, TryStreamExt as _};
231}
232
233#[cfg(all(
234    not(feature = "backtraces"),
235    not(feature = "backtraces-impl-backtrace-crate"),
236    not(feature = "backtraces-impl-std"),
237))]
238mod backtrace_inert;
239#[cfg(all(
240    not(feature = "backtraces"),
241    not(feature = "backtraces-impl-backtrace-crate"),
242    not(feature = "backtraces-impl-std"),
243))]
244pub use crate::backtrace_inert::*;
245
246#[cfg(all(
247    feature = "backtraces",
248    not(feature = "backtraces-impl-backtrace-crate"),
249    not(feature = "backtraces-impl-std"),
250))]
251mod backtrace_shim;
252#[cfg(all(
253    feature = "backtraces",
254    not(feature = "backtraces-impl-backtrace-crate"),
255    not(feature = "backtraces-impl-std"),
256))]
257pub use crate::backtrace_shim::*;
258
259#[cfg(any(feature = "std", test))]
260mod once_bool;
261
262#[cfg(feature = "backtraces-impl-backtrace-crate")]
263pub use backtrace::Backtrace;
264
265#[cfg(feature = "backtraces-impl-std")]
266pub use std::backtrace::Backtrace;
267
268#[cfg(feature = "futures")]
269pub mod futures;
270
271mod error_chain;
272pub use crate::error_chain::*;
273
274mod report;
275#[cfg(feature = "std")]
276pub use report::CleanedErrorText;
277pub use report::{Report, __InternalExtractErrorType};
278
279doc_comment::doc_comment! {
280    include_str!("Snafu.md"),
281    pub use snafu_derive::Snafu;
282}
283
284doc_comment::doc_comment! {
285    include_str!("report.md"),
286    pub use snafu_derive::report;
287}
288
289macro_rules! generate_guide {
290    (pub mod $name:ident { $($children:tt)* } $($rest:tt)*) => {
291        generate_guide!(@gen ".", pub mod $name { $($children)* } $($rest)*);
292    };
293    (@gen $prefix:expr, ) => {};
294    (@gen $prefix:expr, pub mod $name:ident; $($rest:tt)*) => {
295        generate_guide!(@gen $prefix, pub mod $name { } $($rest)*);
296    };
297    (@gen $prefix:expr, @code pub mod $name:ident; $($rest:tt)*) => {
298        #[cfg(feature = "guide")]
299        pub mod $name;
300
301        #[cfg(not(feature = "guide"))]
302        /// Not currently built; please add the `guide` feature flag.
303        pub mod $name {}
304
305        generate_guide!(@gen $prefix, $($rest)*);
306    };
307    (@gen $prefix:expr, pub mod $name:ident { $($children:tt)* } $($rest:tt)*) => {
308        #[cfg(feature = "guide")]
309        doc_comment::doc_comment! {
310            include_str!(concat!($prefix, "/", stringify!($name), ".md")),
311            pub mod $name {
312                generate_guide!(@gen concat!($prefix, "/", stringify!($name)), $($children)*);
313            }
314        }
315        #[cfg(not(feature = "guide"))]
316        /// Not currently built; please add the `guide` feature flag.
317        pub mod $name {
318            generate_guide!(@gen concat!($prefix, "/", stringify!($name)), $($children)*);
319        }
320
321        generate_guide!(@gen $prefix, $($rest)*);
322    };
323}
324
325generate_guide! {
326    pub mod guide {
327        pub mod comparison {
328            pub mod failure;
329        }
330        pub mod compatibility;
331        pub mod feature_flags;
332        pub mod generics;
333        pub mod opaque;
334        pub mod philosophy;
335        pub mod structs;
336        pub mod what_code_is_generated;
337        pub mod troubleshooting {
338            pub mod missing_field_source;
339        }
340        pub mod upgrading;
341
342        @code pub mod examples;
343    }
344}
345
346doc_comment::doctest!("../README.md", readme_tests);
347
348#[cfg(feature = "unstable-core-error")]
349#[doc(hidden)]
350pub use core::error::Error;
351
352#[cfg(all(not(feature = "unstable-core-error"), any(feature = "std", test)))]
353#[doc(hidden)]
354pub use std::error::Error;
355
356#[cfg(not(any(feature = "unstable-core-error", feature = "std", test)))]
357mod no_std_error;
358#[cfg(not(any(feature = "unstable-core-error", feature = "std", test)))]
359#[doc(hidden)]
360pub use no_std_error::Error;
361
362/// Ensure a condition is true. If it is not, return from the function
363/// with an error.
364///
365/// ## Examples
366///
367/// ```rust
368/// use snafu::prelude::*;
369///
370/// #[derive(Debug, Snafu)]
371/// enum Error {
372///     InvalidUser { user_id: i32 },
373/// }
374///
375/// fn example(user_id: i32) -> Result<(), Error> {
376///     ensure!(user_id > 0, InvalidUserSnafu { user_id });
377///     // After this point, we know that `user_id` is positive.
378///     let user_id = user_id as u32;
379///     Ok(())
380/// }
381/// ```
382#[macro_export]
383macro_rules! ensure {
384    ($predicate:expr, $context_selector:expr $(,)?) => {
385        if !$predicate {
386            return $context_selector
387                .fail()
388                .map_err(::core::convert::Into::into);
389        }
390    };
391}
392
393/// Instantiate and return a stringly-typed error message.
394///
395/// This can be used with the provided [`Whatever`][] type or with a
396/// custom error type that uses `snafu(whatever)`.
397///
398/// # Without an underlying error
399///
400/// Provide a format string and any optional arguments. The macro will
401/// unconditionally exit the calling function with an error.
402///
403/// ## Examples
404///
405/// ```rust
406/// use snafu::{Whatever, prelude::*};
407///
408/// type Result<T, E = Whatever> = std::result::Result<T, E>;
409///
410/// enum Status {
411///     Sleeping,
412///     Chilling,
413///     Working,
414/// }
415///
416/// # fn stand_up() {}
417/// # fn go_downstairs() {}
418/// fn do_laundry(status: Status, items: u8) -> Result<()> {
419///     match status {
420///         Status::Sleeping => whatever!("Cannot launder {items} clothes when I am asleep"),
421///         Status::Chilling => {
422///             stand_up();
423///             go_downstairs();
424///         }
425///         Status::Working => {
426///             go_downstairs();
427///         }
428///     }
429///     Ok(())
430/// }
431/// ```
432///
433/// # With an underlying error
434///
435/// Provide a `Result` as the first argument, followed by a format
436/// string and any optional arguments. If the `Result` is an error,
437/// the formatted string will be appended to the error and the macro
438/// will exit the calling function with an error. If the `Result` is
439/// not an error, the macro will evaluate to the `Ok` value of the
440/// `Result`.
441///
442/// ## Examples
443///
444/// ```rust
445/// use snafu::prelude::*;
446///
447/// #[derive(Debug, Snafu)]
448/// #[snafu(whatever, display("Error was: {message}"))]
449/// struct Error {
450///     message: String,
451///     #[snafu(source(from(Box<dyn std::error::Error>, Some)))]
452///     source: Option<Box<dyn std::error::Error>>,
453/// }
454/// type Result<T, E = Error> = std::result::Result<T, E>;
455///
456/// fn calculate_brightness_factor() -> Result<u8> {
457///     let angle = calculate_angle_of_refraction();
458///     let angle = whatever!(angle, "There was no angle");
459///     Ok(angle * 2)
460/// }
461///
462/// fn calculate_angle_of_refraction() -> Result<u8> {
463///     whatever!("The programmer forgot to implement this...");
464/// }
465/// ```
466#[macro_export]
467#[cfg(any(feature = "std", test))]
468macro_rules! whatever {
469    ($fmt:literal$(, $($arg:expr),* $(,)?)?) => {
470        return core::result::Result::Err({
471            $crate::FromString::without_source(
472                format!($fmt$(, $($arg),*)*),
473            )
474        });
475    };
476    ($source:expr, $fmt:literal$(, $($arg:expr),* $(,)?)*) => {
477        match $source {
478            core::result::Result::Ok(v) => v,
479            core::result::Result::Err(e) => {
480                return core::result::Result::Err({
481                    $crate::FromString::with_source(
482                        core::convert::Into::into(e),
483                        format!($fmt$(, $($arg),*)*),
484                    )
485                });
486            }
487        }
488    };
489}
490
491/// Ensure a condition is true. If it is not, return a stringly-typed
492/// error message.
493///
494/// This can be used with the provided [`Whatever`][] type or with a
495/// custom error type that uses `snafu(whatever)`.
496///
497/// ## Examples
498///
499/// ```rust
500/// use snafu::prelude::*;
501///
502/// #[derive(Debug, Snafu)]
503/// #[snafu(whatever, display("Error was: {message}"))]
504/// struct Error {
505///     message: String,
506/// }
507/// type Result<T, E = Error> = std::result::Result<T, E>;
508///
509/// fn get_bank_account_balance(account_id: &str) -> Result<u8> {
510/// # fn moon_is_rising() -> bool { false }
511///     ensure_whatever!(
512///         moon_is_rising(),
513///         "We are recalibrating the dynamos for account {}, sorry",
514///         account_id,
515///     );
516///
517///     Ok(100)
518/// }
519/// ```
520#[macro_export]
521#[cfg(any(feature = "std", test))]
522macro_rules! ensure_whatever {
523    ($predicate:expr, $fmt:literal$(, $($arg:expr),* $(,)?)?) => {
524        if !$predicate {
525            $crate::whatever!($fmt$(, $($arg),*)*);
526        }
527    };
528}
529
530/// Additions to [`Result`](std::result::Result).
531pub trait ResultExt<T, E>: Sized {
532    /// Extend a [`Result`]'s error with additional context-sensitive information.
533    ///
534    /// [`Result`]: std::result::Result
535    ///
536    /// ```rust
537    /// use snafu::prelude::*;
538    ///
539    /// #[derive(Debug, Snafu)]
540    /// enum Error {
541    ///     Authenticating {
542    ///         user_name: String,
543    ///         user_id: i32,
544    ///         source: ApiError,
545    ///     },
546    /// }
547    ///
548    /// fn example() -> Result<(), Error> {
549    ///     another_function().context(AuthenticatingSnafu {
550    ///         user_name: "admin",
551    ///         user_id: 42,
552    ///     })?;
553    ///     Ok(())
554    /// }
555    ///
556    /// # type ApiError = Box<dyn std::error::Error>;
557    /// fn another_function() -> Result<i32, ApiError> {
558    ///     /* ... */
559    /// # Ok(42)
560    /// }
561    /// ```
562    ///
563    /// Note that the context selector will call
564    /// [`Into::into`](std::convert::Into::into) on each field, so the types
565    /// are not required to exactly match.
566    fn context<C, E2>(self, context: C) -> Result<T, E2>
567    where
568        C: IntoError<E2, Source = E>,
569        E2: Error + ErrorCompat;
570
571    /// Extend a [`Result`][]'s error with lazily-generated context-sensitive information.
572    ///
573    /// [`Result`]: std::result::Result
574    ///
575    /// ```rust
576    /// use snafu::prelude::*;
577    ///
578    /// #[derive(Debug, Snafu)]
579    /// enum Error {
580    ///     Authenticating {
581    ///         user_name: String,
582    ///         user_id: i32,
583    ///         source: ApiError,
584    ///     },
585    /// }
586    ///
587    /// fn example() -> Result<(), Error> {
588    ///     another_function().with_context(|_| AuthenticatingSnafu {
589    ///         user_name: "admin".to_string(),
590    ///         user_id: 42,
591    ///     })?;
592    ///     Ok(())
593    /// }
594    ///
595    /// # type ApiError = std::io::Error;
596    /// fn another_function() -> Result<i32, ApiError> {
597    ///     /* ... */
598    /// # Ok(42)
599    /// }
600    /// ```
601    ///
602    /// Note that this *may not* be needed in many cases because the context
603    /// selector will call [`Into::into`](std::convert::Into::into) on each
604    /// field.
605    fn with_context<F, C, E2>(self, context: F) -> Result<T, E2>
606    where
607        F: FnOnce(&mut E) -> C,
608        C: IntoError<E2, Source = E>,
609        E2: Error + ErrorCompat;
610
611    /// Extend a [`Result`]'s error with information from a string.
612    ///
613    /// The target error type must implement [`FromString`] by using
614    /// the
615    /// [`#[snafu(whatever)]`][Snafu#controlling-stringly-typed-errors]
616    /// attribute. The premade [`Whatever`] type is also available.
617    ///
618    /// In many cases, you will want to use
619    /// [`with_whatever_context`][Self::with_whatever_context] instead
620    /// as it gives you access to the error and is only called in case
621    /// of error. This method is best suited for when you have a
622    /// string literal.
623    ///
624    /// ```rust
625    /// use snafu::{prelude::*, Whatever};
626    ///
627    /// fn example() -> Result<(), Whatever> {
628    ///     std::fs::read_to_string("/this/does/not/exist")
629    ///         .whatever_context("couldn't open the file")?;
630    ///     Ok(())
631    /// }
632    ///
633    /// let err = example().unwrap_err();
634    /// assert_eq!("couldn't open the file", err.to_string());
635    /// ```
636    #[cfg(any(feature = "std", test))]
637    fn whatever_context<S, E2>(self, context: S) -> Result<T, E2>
638    where
639        S: Into<String>,
640        E2: FromString,
641        E: Into<E2::Source>;
642
643    /// Extend a [`Result`]'s error with information from a
644    /// lazily-generated string.
645    ///
646    /// The target error type must implement [`FromString`] by using
647    /// the
648    /// [`#[snafu(whatever)]`][Snafu#controlling-stringly-typed-errors]
649    /// attribute. The premade [`Whatever`] type is also available.
650    ///
651    /// ```rust
652    /// use snafu::{prelude::*, Whatever};
653    ///
654    /// fn example() -> Result<(), Whatever> {
655    ///     let filename = "/this/does/not/exist";
656    ///     std::fs::read_to_string(filename)
657    ///         .with_whatever_context(|_| format!("couldn't open the file {}", filename))?;
658    ///     Ok(())
659    /// }
660    ///
661    /// let err = example().unwrap_err();
662    /// assert_eq!(
663    ///     "couldn't open the file /this/does/not/exist",
664    ///     err.to_string(),
665    /// );
666    /// ```
667    ///
668    /// The closure is not called when the `Result` is `Ok`:
669    ///
670    /// ```rust
671    /// use snafu::{prelude::*, Whatever};
672    ///
673    /// let value: std::io::Result<i32> = Ok(42);
674    /// let result = value.with_whatever_context::<_, String, Whatever>(|_| {
675    ///     panic!("This block will not be evaluated");
676    /// });
677    ///
678    /// assert!(result.is_ok());
679    /// ```
680    #[cfg(any(feature = "std", test))]
681    fn with_whatever_context<F, S, E2>(self, context: F) -> Result<T, E2>
682    where
683        F: FnOnce(&mut E) -> S,
684        S: Into<String>,
685        E2: FromString,
686        E: Into<E2::Source>;
687}
688
689impl<T, E> ResultExt<T, E> for Result<T, E> {
690    #[cfg_attr(feature = "rust_1_46", track_caller)]
691    fn context<C, E2>(self, context: C) -> Result<T, E2>
692    where
693        C: IntoError<E2, Source = E>,
694        E2: Error + ErrorCompat,
695    {
696        // https://github.com/rust-lang/rust/issues/74042
697        match self {
698            Ok(v) => Ok(v),
699            Err(error) => Err(context.into_error(error)),
700        }
701    }
702
703    #[cfg_attr(feature = "rust_1_46", track_caller)]
704    fn with_context<F, C, E2>(self, context: F) -> Result<T, E2>
705    where
706        F: FnOnce(&mut E) -> C,
707        C: IntoError<E2, Source = E>,
708        E2: Error + ErrorCompat,
709    {
710        // https://github.com/rust-lang/rust/issues/74042
711        match self {
712            Ok(v) => Ok(v),
713            Err(mut error) => {
714                let context = context(&mut error);
715                Err(context.into_error(error))
716            }
717        }
718    }
719
720    #[cfg(any(feature = "std", test))]
721    #[cfg_attr(feature = "rust_1_46", track_caller)]
722    fn whatever_context<S, E2>(self, context: S) -> Result<T, E2>
723    where
724        S: Into<String>,
725        E2: FromString,
726        E: Into<E2::Source>,
727    {
728        // https://github.com/rust-lang/rust/issues/74042
729        match self {
730            Ok(v) => Ok(v),
731            Err(error) => Err(FromString::with_source(error.into(), context.into())),
732        }
733    }
734
735    #[cfg(any(feature = "std", test))]
736    #[cfg_attr(feature = "rust_1_46", track_caller)]
737    fn with_whatever_context<F, S, E2>(self, context: F) -> Result<T, E2>
738    where
739        F: FnOnce(&mut E) -> S,
740        S: Into<String>,
741        E2: FromString,
742        E: Into<E2::Source>,
743    {
744        // https://github.com/rust-lang/rust/issues/74042
745        match self {
746            Ok(t) => Ok(t),
747            Err(mut e) => {
748                let context = context(&mut e);
749                Err(FromString::with_source(e.into(), context.into()))
750            }
751        }
752    }
753}
754
755/// A temporary error type used when converting an [`Option`][] into a
756/// [`Result`][]
757///
758/// [`Option`]: std::option::Option
759/// [`Result`]: std::result::Result
760pub struct NoneError;
761
762/// Additions to [`Option`](std::option::Option).
763pub trait OptionExt<T>: Sized {
764    /// Convert an [`Option`][] into a [`Result`][] with additional
765    /// context-sensitive information.
766    ///
767    /// [Option]: std::option::Option
768    /// [Result]: std::option::Result
769    ///
770    /// ```rust
771    /// use snafu::prelude::*;
772    ///
773    /// #[derive(Debug, Snafu)]
774    /// enum Error {
775    ///     UserLookup { user_id: i32 },
776    /// }
777    ///
778    /// fn example(user_id: i32) -> Result<(), Error> {
779    ///     let name = username(user_id).context(UserLookupSnafu { user_id })?;
780    ///     println!("Username was {}", name);
781    ///     Ok(())
782    /// }
783    ///
784    /// fn username(user_id: i32) -> Option<String> {
785    ///     /* ... */
786    /// # None
787    /// }
788    /// ```
789    ///
790    /// Note that the context selector will call
791    /// [`Into::into`](std::convert::Into::into) on each field, so the types
792    /// are not required to exactly match.
793    fn context<C, E>(self, context: C) -> Result<T, E>
794    where
795        C: IntoError<E, Source = NoneError>,
796        E: Error + ErrorCompat;
797
798    /// Convert an [`Option`][] into a [`Result`][] with
799    /// lazily-generated context-sensitive information.
800    ///
801    /// [`Option`]: std::option::Option
802    /// [`Result`]: std::result::Result
803    ///
804    /// ```
805    /// use snafu::prelude::*;
806    ///
807    /// #[derive(Debug, Snafu)]
808    /// enum Error {
809    ///     UserLookup {
810    ///         user_id: i32,
811    ///         previous_ids: Vec<i32>,
812    ///     },
813    /// }
814    ///
815    /// fn example(user_id: i32) -> Result<(), Error> {
816    ///     let name = username(user_id).with_context(|| UserLookupSnafu {
817    ///         user_id,
818    ///         previous_ids: Vec::new(),
819    ///     })?;
820    ///     println!("Username was {}", name);
821    ///     Ok(())
822    /// }
823    ///
824    /// fn username(user_id: i32) -> Option<String> {
825    ///     /* ... */
826    /// # None
827    /// }
828    /// ```
829    ///
830    /// Note that this *may not* be needed in many cases because the context
831    /// selector will call [`Into::into`](std::convert::Into::into) on each
832    /// field.
833    fn with_context<F, C, E>(self, context: F) -> Result<T, E>
834    where
835        F: FnOnce() -> C,
836        C: IntoError<E, Source = NoneError>,
837        E: Error + ErrorCompat;
838
839    /// Convert an [`Option`] into a [`Result`] with information
840    /// from a string.
841    ///
842    /// The target error type must implement [`FromString`] by using
843    /// the
844    /// [`#[snafu(whatever)]`][Snafu#controlling-stringly-typed-errors]
845    /// attribute. The premade [`Whatever`] type is also available.
846    ///
847    /// In many cases, you will want to use
848    /// [`with_whatever_context`][Self::with_whatever_context] instead
849    /// as it is only called in case of error. This method is best
850    /// suited for when you have a string literal.
851    ///
852    /// ```rust
853    /// use snafu::{prelude::*, Whatever};
854    ///
855    /// fn example(env_var_name: &str) -> Result<(), Whatever> {
856    ///     std::env::var_os(env_var_name).whatever_context("couldn't get the environment variable")?;
857    ///     Ok(())
858    /// }
859    ///
860    /// let err = example("UNDEFINED_ENVIRONMENT_VARIABLE").unwrap_err();
861    /// assert_eq!("couldn't get the environment variable", err.to_string());
862    /// ```
863    #[cfg(any(feature = "std", test))]
864    fn whatever_context<S, E>(self, context: S) -> Result<T, E>
865    where
866        S: Into<String>,
867        E: FromString;
868
869    /// Convert an [`Option`] into a [`Result`][] with information from a
870    /// lazily-generated string.
871    ///
872    /// The target error type must implement [`FromString`][] by using
873    /// the
874    /// [`#[snafu(whatever)]`][Snafu#controlling-stringly-typed-errors]
875    /// attribute. The premade [`Whatever`][] type is also available.
876    ///
877    /// ```rust
878    /// use snafu::{prelude::*, Whatever};
879    ///
880    /// fn example(env_var_name: &str) -> Result<(), Whatever> {
881    ///     std::env::var_os(env_var_name).with_whatever_context(|| {
882    ///         format!("couldn't get the environment variable {}", env_var_name)
883    ///     })?;
884    ///     Ok(())
885    /// }
886    ///
887    /// let err = example("UNDEFINED_ENVIRONMENT_VARIABLE").unwrap_err();
888    /// assert_eq!(
889    ///     "couldn't get the environment variable UNDEFINED_ENVIRONMENT_VARIABLE",
890    ///     err.to_string()
891    /// );
892    /// ```
893    ///
894    /// The closure is not called when the `Option` is `Some`:
895    ///
896    /// ```rust
897    /// use snafu::{prelude::*, Whatever};
898    ///
899    /// let value = Some(42);
900    /// let result = value.with_whatever_context::<_, String, Whatever>(|| {
901    ///     panic!("This block will not be evaluated");
902    /// });
903    ///
904    /// assert!(result.is_ok());
905    /// ```
906    #[cfg(any(feature = "std", test))]
907    fn with_whatever_context<F, S, E>(self, context: F) -> Result<T, E>
908    where
909        F: FnOnce() -> S,
910        S: Into<String>,
911        E: FromString;
912}
913
914impl<T> OptionExt<T> for Option<T> {
915    #[cfg_attr(feature = "rust_1_46", track_caller)]
916    fn context<C, E>(self, context: C) -> Result<T, E>
917    where
918        C: IntoError<E, Source = NoneError>,
919        E: Error + ErrorCompat,
920    {
921        // https://github.com/rust-lang/rust/issues/74042
922        match self {
923            Some(v) => Ok(v),
924            None => Err(context.into_error(NoneError)),
925        }
926    }
927
928    #[cfg_attr(feature = "rust_1_46", track_caller)]
929    fn with_context<F, C, E>(self, context: F) -> Result<T, E>
930    where
931        F: FnOnce() -> C,
932        C: IntoError<E, Source = NoneError>,
933        E: Error + ErrorCompat,
934    {
935        // https://github.com/rust-lang/rust/issues/74042
936        match self {
937            Some(v) => Ok(v),
938            None => Err(context().into_error(NoneError)),
939        }
940    }
941
942    #[cfg(any(feature = "std", test))]
943    #[cfg_attr(feature = "rust_1_46", track_caller)]
944    fn whatever_context<S, E>(self, context: S) -> Result<T, E>
945    where
946        S: Into<String>,
947        E: FromString,
948    {
949        match self {
950            Some(v) => Ok(v),
951            None => Err(FromString::without_source(context.into())),
952        }
953    }
954
955    #[cfg(any(feature = "std", test))]
956    #[cfg_attr(feature = "rust_1_46", track_caller)]
957    fn with_whatever_context<F, S, E>(self, context: F) -> Result<T, E>
958    where
959        F: FnOnce() -> S,
960        S: Into<String>,
961        E: FromString,
962    {
963        match self {
964            Some(v) => Ok(v),
965            None => {
966                let context = context();
967                Err(FromString::without_source(context.into()))
968            }
969        }
970    }
971}
972
973/// Backports changes to the [`Error`](std::error::Error) trait to
974/// versions of Rust lacking them.
975///
976/// It is recommended to always call these methods explicitly so that
977/// it is easy to replace usages of this trait when you start
978/// supporting a newer version of Rust.
979///
980/// ```
981/// # use snafu::{prelude::*, ErrorCompat};
982/// # #[derive(Debug, Snafu)] enum Example {};
983/// # fn example(error: Example) {
984/// ErrorCompat::backtrace(&error); // Recommended
985/// error.backtrace();              // Discouraged
986/// # }
987/// ```
988pub trait ErrorCompat {
989    /// Returns a [`Backtrace`](Backtrace) that may be printed.
990    fn backtrace(&self) -> Option<&Backtrace> {
991        None
992    }
993
994    /// Returns an iterator for traversing the chain of errors,
995    /// starting with the current error
996    /// and continuing with recursive calls to `Error::source`.
997    ///
998    /// To omit the current error and only traverse its sources,
999    /// use `skip(1)`.
1000    fn iter_chain(&self) -> ChainCompat
1001    where
1002        Self: AsErrorSource,
1003    {
1004        ChainCompat::new(self.as_error_source())
1005    }
1006}
1007
1008impl<'a, E> ErrorCompat for &'a E
1009where
1010    E: ErrorCompat,
1011{
1012    fn backtrace(&self) -> Option<&Backtrace> {
1013        (**self).backtrace()
1014    }
1015}
1016
1017#[cfg(any(feature = "std", test))]
1018impl<E> ErrorCompat for Box<E>
1019where
1020    E: ErrorCompat,
1021{
1022    fn backtrace(&self) -> Option<&Backtrace> {
1023        (**self).backtrace()
1024    }
1025}
1026
1027/// Converts the receiver into an [`Error`][] trait object, suitable
1028/// for use in [`Error::source`][].
1029///
1030/// It is expected that most users of SNAFU will not directly interact
1031/// with this trait.
1032///
1033/// [`Error`]: std::error::Error
1034/// [`Error::source`]: std::error::Error::source
1035//
1036// Given an error enum with multiple types of underlying causes:
1037//
1038// ```rust
1039// enum Error {
1040//     BoxTraitObjectSendSync(Box<dyn error::Error + Send + Sync + 'static>),
1041//     BoxTraitObject(Box<dyn error::Error + 'static>),
1042//     Boxed(Box<io::Error>),
1043//     Unboxed(io::Error),
1044// }
1045// ```
1046//
1047// This trait provides the answer to what consistent expression can go
1048// in each match arm:
1049//
1050// ```rust
1051// impl error::Error for Error {
1052//     fn source(&self) -> Option<&(dyn error::Error + 'static)> {
1053//         use Error::*;
1054//
1055//         let v = match *self {
1056//             BoxTraitObjectSendSync(ref e) => ...,
1057//             BoxTraitObject(ref e) => ...,
1058//             Boxed(ref e) => ...,
1059//             Unboxed(ref e) => ...,
1060//         };
1061//
1062//         Some(v)
1063//     }
1064// }
1065//
1066// Existing methods like returning `e`, `&**e`, `Borrow::borrow(e)`,
1067// `Deref::deref(e)`, and `AsRef::as_ref(e)` do not work for various
1068// reasons.
1069pub trait AsErrorSource {
1070    /// For maximum effectiveness, this needs to be called as a method
1071    /// to benefit from Rust's automatic dereferencing of method
1072    /// receivers.
1073    fn as_error_source(&self) -> &(dyn Error + 'static);
1074}
1075
1076impl AsErrorSource for dyn Error + 'static {
1077    fn as_error_source(&self) -> &(dyn Error + 'static) {
1078        self
1079    }
1080}
1081
1082impl AsErrorSource for dyn Error + Send + 'static {
1083    fn as_error_source(&self) -> &(dyn Error + 'static) {
1084        self
1085    }
1086}
1087
1088impl AsErrorSource for dyn Error + Sync + 'static {
1089    fn as_error_source(&self) -> &(dyn Error + 'static) {
1090        self
1091    }
1092}
1093
1094impl AsErrorSource for dyn Error + Send + Sync + 'static {
1095    fn as_error_source(&self) -> &(dyn Error + 'static) {
1096        self
1097    }
1098}
1099
1100impl<T> AsErrorSource for T
1101where
1102    T: Error + 'static,
1103{
1104    fn as_error_source(&self) -> &(dyn Error + 'static) {
1105        self
1106    }
1107}
1108
1109/// Combines an underlying error with additional information
1110/// about the error.
1111///
1112/// It is expected that most users of SNAFU will not directly interact
1113/// with this trait.
1114pub trait IntoError<E>
1115where
1116    E: Error + ErrorCompat,
1117{
1118    /// The underlying error
1119    type Source;
1120
1121    /// Combine the information to produce the error
1122    fn into_error(self, source: Self::Source) -> E;
1123}
1124
1125/// Takes a string message and builds the corresponding error.
1126///
1127/// It is expected that most users of SNAFU will not directly interact
1128/// with this trait.
1129#[cfg(any(feature = "std", test))]
1130pub trait FromString {
1131    /// The underlying error
1132    type Source;
1133
1134    /// Create a brand new error from the given string
1135    fn without_source(message: String) -> Self;
1136
1137    /// Wrap an existing error with the given string
1138    fn with_source(source: Self::Source, message: String) -> Self;
1139}
1140
1141/// Construct data to be included as part of an error. The data must
1142/// require no arguments to be created.
1143pub trait GenerateImplicitData {
1144    /// Build the data.
1145    fn generate() -> Self;
1146
1147    /// Build the data using the given source
1148    #[cfg_attr(feature = "rust_1_46", track_caller)]
1149    fn generate_with_source(source: &dyn crate::Error) -> Self
1150    where
1151        Self: Sized,
1152    {
1153        let _source = source;
1154        Self::generate()
1155    }
1156}
1157
1158/// View a backtrace-like value as an optional backtrace.
1159pub trait AsBacktrace {
1160    /// Retrieve the optional backtrace
1161    fn as_backtrace(&self) -> Option<&Backtrace>;
1162}
1163
1164/// Only create a backtrace when an environment variable is set.
1165///
1166/// This looks first for the value of `RUST_LIB_BACKTRACE` then
1167/// `RUST_BACKTRACE`. If the value is set to `1`, backtraces will be
1168/// enabled.
1169///
1170/// This value will be tested only once per program execution;
1171/// changing the environment variable after it has been checked will
1172/// have no effect.
1173///
1174/// ## Interaction with the Provider API
1175///
1176/// If you enable the [`unstable-provider-api` feature
1177/// flag][provider-ff], a backtrace will not be captured if the
1178/// original error is able to provide a `Backtrace`, even if the
1179/// appropriate environment variables are set. This prevents capturing
1180/// a redundant backtrace.
1181///
1182/// [provider-ff]: crate::guide::feature_flags#unstable-provider-api
1183#[cfg(any(feature = "std", test))]
1184impl GenerateImplicitData for Option<Backtrace> {
1185    fn generate() -> Self {
1186        if backtrace_collection_enabled() {
1187            Some(Backtrace::generate())
1188        } else {
1189            None
1190        }
1191    }
1192
1193    fn generate_with_source(source: &dyn crate::Error) -> Self {
1194        #[cfg(feature = "unstable-provider-api")]
1195        {
1196            use core::any;
1197
1198            if !backtrace_collection_enabled() {
1199                None
1200            } else if any::request_ref::<Backtrace>(source).is_some() {
1201                None
1202            } else {
1203                Some(Backtrace::generate_with_source(source))
1204            }
1205        }
1206
1207        #[cfg(not(feature = "unstable-provider-api"))]
1208        {
1209            let _source = source;
1210            Self::generate()
1211        }
1212    }
1213}
1214
1215#[cfg(any(feature = "std", test))]
1216impl AsBacktrace for Option<Backtrace> {
1217    fn as_backtrace(&self) -> Option<&Backtrace> {
1218        self.as_ref()
1219    }
1220}
1221
1222#[cfg(any(feature = "std", test))]
1223fn backtrace_collection_enabled() -> bool {
1224    use crate::once_bool::OnceBool;
1225    use std::env;
1226
1227    static ENABLED: OnceBool = OnceBool::new();
1228
1229    ENABLED.get(|| {
1230        // TODO: What values count as "true"?
1231        env::var_os("RUST_LIB_BACKTRACE")
1232            .or_else(|| env::var_os("RUST_BACKTRACE"))
1233            .map_or(false, |v| v == "1")
1234    })
1235}
1236
1237#[cfg(feature = "backtraces-impl-backtrace-crate")]
1238impl GenerateImplicitData for Backtrace {
1239    fn generate() -> Self {
1240        Backtrace::new()
1241    }
1242}
1243
1244#[cfg(feature = "backtraces-impl-backtrace-crate")]
1245impl AsBacktrace for Backtrace {
1246    fn as_backtrace(&self) -> Option<&Backtrace> {
1247        Some(self)
1248    }
1249}
1250
1251#[cfg(feature = "backtraces-impl-std")]
1252impl GenerateImplicitData for Backtrace {
1253    fn generate() -> Self {
1254        Backtrace::force_capture()
1255    }
1256}
1257
1258#[cfg(feature = "backtraces-impl-std")]
1259impl AsBacktrace for Backtrace {
1260    fn as_backtrace(&self) -> Option<&Backtrace> {
1261        Some(self)
1262    }
1263}
1264
1265/// The source code location where the error was reported.
1266///
1267/// To use it, add a field `location: Location` to your error. This
1268/// will automatically register it as [implicitly generated
1269/// data][implicit].
1270///
1271/// [implicit]: Snafu#controlling-implicitly-generated-data
1272///
1273/// ## Limitations
1274///
1275/// ### Rust 1.46
1276///
1277/// You need to enable the [`rust_1_46` feature flag][flag] for
1278/// implicit location capture. If you cannot enable that, you can
1279/// still use the [`location!`] macro at the expense of more typing.
1280///
1281/// [flag]: guide::compatibility#rust_1_46
1282///
1283/// ### Disabled context selectors
1284///
1285/// If you have [disabled the context selector][disabled], SNAFU will
1286/// not be able to capture an accurate location.
1287///
1288/// As a workaround, re-enable the context selector.
1289///
1290/// [disabled]: Snafu#disabling-the-context-selector
1291///
1292/// ### Asynchronous code
1293///
1294/// When using SNAFU's
1295#[cfg_attr(feature = "futures", doc = " [`TryFutureExt`][futures::TryFutureExt]")]
1296#[cfg_attr(not(feature = "futures"), doc = " `TryFutureExt`")]
1297/// or
1298#[cfg_attr(feature = "futures", doc = " [`TryStreamExt`][futures::TryStreamExt]")]
1299#[cfg_attr(not(feature = "futures"), doc = " `TryStreamExt`")]
1300/// extension traits, the automatically captured location will
1301/// correspond to where the future or stream was **polled**, not where
1302/// it was created. Additionally, many `Future` or `Stream`
1303/// combinators do not forward the caller's location to their
1304/// closures, causing the recorded location to be inside of the future
1305/// combinator's library.
1306///
1307/// There are two workarounds:
1308/// 1. Use the [`location!`] macro
1309/// 1. Use [`ResultExt`] instead
1310///
1311/// ```rust
1312/// # #[cfg(feature = "futures")] {
1313/// # use snafu::{prelude::*, Location, location};
1314/// // Non-ideal: will report where `wrapped_error_future` is `.await`ed.
1315/// # let error_future = async { AnotherSnafu.fail::<()>() };
1316/// let wrapped_error_future = error_future.context(ImplicitLocationSnafu);
1317///
1318/// // Better: will report the location of `.context`.
1319/// # let error_future = async { AnotherSnafu.fail::<()>() };
1320/// let wrapped_error_future = async { error_future.await.context(ImplicitLocationSnafu) };
1321///
1322/// // Better: Will report the location of `location!`
1323/// # let error_future = async { AnotherSnafu.fail::<()>() };
1324/// let wrapped_error_future = error_future.with_context(|_| ExplicitLocationSnafu {
1325///     location: location!(),
1326/// });
1327///
1328/// # #[derive(Debug, Snafu)] struct AnotherError;
1329/// #[derive(Debug, Snafu)]
1330/// struct ImplicitLocationError {
1331///     source: AnotherError,
1332///     location: Location,
1333/// }
1334///
1335/// #[derive(Debug, Snafu)]
1336/// struct ExplicitLocationError {
1337///     source: AnotherError,
1338///     #[snafu(implicit(false))]
1339///     location: Location,
1340/// }
1341/// # }
1342/// ```
1343#[derive(Copy, Clone)]
1344pub struct Location {
1345    /// The file where the error was reported
1346    pub file: &'static str,
1347    /// The line where the error was reported
1348    pub line: u32,
1349    /// The column where the error was reported
1350    pub column: u32,
1351
1352    // Use `#[non_exhaustive]` when we upgrade to Rust 1.40
1353    _other: (),
1354}
1355
1356impl Location {
1357    /// Constructs a `Location` using the given information
1358    pub fn new(file: &'static str, line: u32, column: u32) -> Self {
1359        Self {
1360            file,
1361            line,
1362            column,
1363            _other: (),
1364        }
1365    }
1366}
1367
1368#[cfg(feature = "rust_1_46")]
1369impl Default for Location {
1370    #[track_caller]
1371    fn default() -> Self {
1372        let loc = core::panic::Location::caller();
1373        Self {
1374            file: loc.file(),
1375            line: loc.line(),
1376            column: loc.column(),
1377            _other: (),
1378        }
1379    }
1380}
1381
1382#[cfg(feature = "rust_1_46")]
1383impl GenerateImplicitData for Location {
1384    #[inline]
1385    #[track_caller]
1386    fn generate() -> Self {
1387        Self::default()
1388    }
1389}
1390
1391impl fmt::Debug for Location {
1392    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1393        f.debug_struct("Location")
1394            .field("file", &self.file)
1395            .field("line", &self.line)
1396            .field("column", &self.column)
1397            .finish()
1398    }
1399}
1400
1401impl fmt::Display for Location {
1402    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1403        write!(
1404            f,
1405            "{file}:{line}:{column}",
1406            file = self.file,
1407            line = self.line,
1408            column = self.column,
1409        )
1410    }
1411}
1412
1413/// Constructs a [`Location`] using the current file, line, and column.
1414#[macro_export]
1415macro_rules! location {
1416    () => {
1417        Location::new(file!(), line!(), column!())
1418    };
1419}
1420
1421/// A basic error type that you can use as a first step to better
1422/// error handling.
1423///
1424/// You can use this type in your own application as a quick way to
1425/// create errors or add basic context to another error. This can also
1426/// be used in a library, but consider wrapping it in an
1427/// [opaque](guide::opaque) error to avoid putting the SNAFU crate in
1428/// your public API.
1429///
1430/// ## Examples
1431///
1432/// ```rust
1433/// use snafu::prelude::*;
1434///
1435/// type Result<T, E = snafu::Whatever> = std::result::Result<T, E>;
1436///
1437/// fn subtract_numbers(a: u32, b: u32) -> Result<u32> {
1438///     if a > b {
1439///         Ok(a - b)
1440///     } else {
1441///         whatever!("Can't subtract {} - {}", a, b)
1442///     }
1443/// }
1444///
1445/// fn complicated_math(a: u32, b: u32) -> Result<u32> {
1446///     let val = subtract_numbers(a, b).whatever_context("Can't do the math")?;
1447///     Ok(val * 2)
1448/// }
1449/// ```
1450///
1451/// See [`whatever!`][] for detailed usage instructions.
1452///
1453/// ## Limitations
1454///
1455/// When wrapping errors, only the backtrace from the shallowest
1456/// function is guaranteed to be available. If you need the deepest
1457/// possible trace, consider creating a custom error type and [using
1458/// `#[snafu(backtrace)]` on the `source`
1459/// field](Snafu#controlling-backtraces). If a best-effort attempt is
1460/// sufficient, see the [`backtrace`][Self::backtrace] method.
1461///
1462/// When the standard library stabilizes backtrace support, this
1463/// behavior may change.
1464#[derive(Debug, Snafu)]
1465#[snafu(crate_root(crate))]
1466#[snafu(whatever)]
1467#[snafu(display("{message}"))]
1468#[snafu(provide(opt, ref, chain, dyn std::error::Error => source.as_deref()))]
1469#[cfg(any(feature = "std", test))]
1470pub struct Whatever {
1471    #[snafu(source(from(Box<dyn std::error::Error>, Some)))]
1472    #[snafu(provide(false))]
1473    source: Option<Box<dyn std::error::Error>>,
1474    message: String,
1475    backtrace: Backtrace,
1476}
1477
1478#[cfg(any(feature = "std", test))]
1479impl Whatever {
1480    /// Gets the backtrace from the deepest `Whatever` error. If none
1481    /// of the underlying errors are `Whatever`, returns the backtrace
1482    /// from when this instance was created.
1483    pub fn backtrace(&self) -> Option<&Backtrace> {
1484        let mut best_backtrace = &self.backtrace;
1485
1486        let mut source = self.source();
1487        while let Some(s) = source {
1488            if let Some(this) = s.downcast_ref::<Self>() {
1489                best_backtrace = &this.backtrace;
1490            }
1491            source = s.source();
1492        }
1493
1494        Some(best_backtrace)
1495    }
1496}