alt_failure/backtrace/
mod.rs

1use core::fmt::{self, Debug, Display};
2
3macro_rules! with_backtrace { ($($i:item)*) => ($(#[cfg(all(feature = "backtrace", feature = "std"))]$i)*) }
4macro_rules! without_backtrace { ($($i:item)*) => ($(#[cfg(not(all(feature = "backtrace", feature = "std")))]$i)*) }
5
6without_backtrace! {
7    /// A `Backtrace`.
8    ///
9    /// This is an opaque wrapper around the backtrace provided by
10    /// libbacktrace. A variety of optimizations have been performed to avoid
11    /// unnecessary or ill-advised work:
12    ///
13    /// - If this crate is compiled in `no_std` compatible mode, `Backtrace`
14    ///   is an empty struct, and will be completely compiled away.
15    /// - If this crate is run without the `RUST_BACKTRACE` environmental
16    ///   variable enabled, the backtrace will not be generated at runtime.
17    /// - Even if a backtrace is generated, the most expensive part of
18    ///   generating a backtrace is symbol resolution. This backtrace does not
19    ///   perform symbol resolution until it is actually read (e.g. by
20    ///   printing it). If the Backtrace is never used for anything, symbols
21    ///   never get resolved.
22    ///
23    /// Even with these optimizations, including a backtrace in your failure
24    /// may not be appropriate to your use case. You are not required to put a
25    /// backtrace in a custom `Fail` type.
26    ///
27    /// > (We have detected that this crate was documented with no_std
28    /// > compatibility turned on. The version of this crate that has been
29    /// > documented here will never generate a backtrace.)
30    pub struct Backtrace {
31        _secret: (),
32    }
33
34    impl Backtrace {
35        /// Constructs a new backtrace. This will only create a real backtrace
36        /// if the crate is compiled in std mode and the `RUST_BACKTRACE`
37        /// environmental variable is activated.
38        ///
39        /// > (We have detected that this crate was documented with no_std
40        /// > compatibility turned on. The version of this crate that has been
41        /// > documented here will never generate a backtrace.)
42        pub fn new() -> Backtrace {
43            Backtrace { _secret: () }
44        }
45
46        #[cfg(feature = "std")]
47        pub(crate) fn none() -> Backtrace {
48            Backtrace { _secret: () }
49        }
50
51        #[cfg(feature = "std")]
52        pub(crate) fn is_none(&self) -> bool {
53            true
54        }
55
56        /// Returns true if displaying this backtrace would be an empty string.
57        ///
58        /// > (We have detected that this crate was documented with no_std
59        /// > compatibility turned on. The version of this crate that has been
60        /// > documented here will never generate a backtrace and this method
61        /// > will always return true.)
62        pub fn is_empty(&self) -> bool {
63            true
64        }
65    }
66
67    impl Default for Backtrace {
68        fn default() -> Backtrace {
69            Backtrace::new()
70        }
71    }
72
73    impl Debug for Backtrace {
74        fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
75            Ok(())
76        }
77    }
78
79    impl Display for Backtrace {
80        fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
81            Ok(())
82        }
83    }
84}
85
86with_backtrace! {
87    extern crate backtrace;
88
89    mod internal;
90
91    use self::internal::InternalBacktrace;
92
93    /// A `Backtrace`.
94    ///
95    /// This is an opaque wrapper around the backtrace provided by
96    /// libbacktrace. A variety of optimizations have been performed to avoid
97    /// unnecessary or ill-advised work:
98    ///
99    /// - If this crate is compiled in `no_std` compatible mode, `Backtrace`
100    ///   is an empty struct, and will be completely compiled away.
101    /// - If this crate is run without the `RUST_BACKTRACE` environmental
102    ///   variable enabled, the backtrace will not be generated at runtime.
103    /// - Even if a backtrace is generated, the most expensive part of
104    ///   generating a backtrace is symbol resolution. This backtrace does not
105    ///   perform symbol resolution until it is actually read (e.g. by
106    ///   printing it). If the Backtrace is never used for anything, symbols
107    ///   never get resolved.
108    ///
109    /// Even with these optimizations, including a backtrace in your failure
110    /// may not be appropriate to your use case. You are not required to put a
111    /// backtrace in a custom `Fail` type.
112    pub struct Backtrace {
113        internal: InternalBacktrace
114    }
115
116    impl Backtrace {
117        /// Constructs a new backtrace. This will only create a real backtrace
118        /// if the crate is compiled in std mode and the `RUST_BACKTRACE`
119        /// environmental variable is activated.
120        pub fn new() -> Backtrace {
121            Backtrace { internal: InternalBacktrace::new() }
122        }
123
124        pub(crate) fn none() -> Backtrace {
125            Backtrace { internal: InternalBacktrace::none() }
126        }
127
128        pub(crate) fn is_none(&self) -> bool {
129            self.internal.is_none()
130        }
131
132        /// Returns true if displaying this backtrace would be an empty string.
133        pub fn is_empty(&self) -> bool {
134            self.internal.is_none()
135        }
136    }
137
138    impl Default for Backtrace {
139        fn default() -> Backtrace {
140            Backtrace::new()
141        }
142    }
143
144    impl Debug for Backtrace {
145        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
146            if let Some(bt) = self.internal.as_backtrace() {
147                Debug::fmt(bt, f)
148            } else { Ok(()) }
149        }
150    }
151
152    impl Display for Backtrace {
153        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
154            if let Some(bt) = self.internal.as_backtrace() {
155                Debug::fmt(bt, f)
156            } else { Ok(()) }
157        }
158    }
159}