error_stack/frame/
frame_impl.rs

1#![expect(deprecated, reason = "We use `Context` to maintain compatibility")]
2
3use alloc::boxed::Box;
4#[cfg(nightly)]
5use core::error::Request;
6use core::{any::Any, error::Error, fmt};
7
8use crate::{AttachmentKind, Context, Frame, FrameKind};
9
10/// Internal representation of a [`Frame`].
11pub(super) trait FrameImpl: Send + Sync + 'static {
12    fn kind(&self) -> FrameKind<'_>;
13
14    fn as_any(&self) -> &dyn Any;
15
16    fn as_any_mut(&mut self) -> &mut dyn Any;
17
18    /// Provide values which can then be requested.
19    #[cfg(nightly)]
20    fn provide<'a>(&'a self, request: &mut Request<'a>);
21}
22
23impl fmt::Debug for Box<dyn FrameImpl> {
24    fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
25        unreachable!()
26    }
27}
28
29impl fmt::Display for Box<dyn FrameImpl> {
30    fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
31        unreachable!()
32    }
33}
34
35impl Error for Box<dyn FrameImpl> {
36    #[cfg(nightly)]
37    fn provide<'a>(&'a self, request: &mut Request<'a>) {
38        (**self).provide(request);
39    }
40}
41
42struct ContextFrame<C> {
43    context: C,
44}
45
46impl<C: Context> FrameImpl for ContextFrame<C> {
47    fn kind(&self) -> FrameKind<'_> {
48        FrameKind::Context(&self.context)
49    }
50
51    fn as_any(&self) -> &dyn Any {
52        &self.context
53    }
54
55    fn as_any_mut(&mut self) -> &mut dyn Any {
56        &mut self.context
57    }
58
59    #[cfg(nightly)]
60    fn provide<'a>(&'a self, request: &mut Request<'a>) {
61        Context::provide(&self.context, request);
62    }
63}
64
65struct AttachmentFrame<A> {
66    attachment: A,
67}
68
69impl<A: 'static + Send + Sync> FrameImpl for AttachmentFrame<A> {
70    fn kind(&self) -> FrameKind<'_> {
71        FrameKind::Attachment(AttachmentKind::Opaque(&self.attachment))
72    }
73
74    fn as_any(&self) -> &dyn Any {
75        &self.attachment
76    }
77
78    fn as_any_mut(&mut self) -> &mut dyn Any {
79        &mut self.attachment
80    }
81
82    #[cfg(nightly)]
83    fn provide<'a>(&'a self, request: &mut Request<'a>) {
84        request.provide_ref(&self.attachment);
85    }
86}
87
88struct PrintableAttachmentFrame<A> {
89    attachment: A,
90}
91
92impl<A: 'static + fmt::Debug + fmt::Display + Send + Sync> FrameImpl
93    for PrintableAttachmentFrame<A>
94{
95    fn kind(&self) -> FrameKind<'_> {
96        FrameKind::Attachment(AttachmentKind::Printable(&self.attachment))
97    }
98
99    fn as_any(&self) -> &dyn Any {
100        &self.attachment
101    }
102
103    fn as_any_mut(&mut self) -> &mut dyn Any {
104        &mut self.attachment
105    }
106
107    #[cfg(nightly)]
108    fn provide<'a>(&'a self, request: &mut Request<'a>) {
109        request.provide_ref(&self.attachment);
110    }
111}
112
113#[cfg(feature = "anyhow")]
114struct AnyhowContext(anyhow::Error);
115
116#[cfg(feature = "anyhow")]
117impl fmt::Debug for AnyhowContext {
118    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
119        fmt::Debug::fmt(&self.0, fmt)
120    }
121}
122
123#[cfg(feature = "anyhow")]
124impl fmt::Display for AnyhowContext {
125    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
126        fmt::Display::fmt(&self.0, fmt)
127    }
128}
129
130#[cfg(feature = "anyhow")]
131impl Context for AnyhowContext {
132    #[cfg(all(nightly, feature = "std"))]
133    #[inline]
134    fn provide<'a>(&'a self, request: &mut Request<'a>) {
135        request.provide_ref(self.0.backtrace());
136    }
137}
138
139#[cfg(feature = "anyhow")]
140impl FrameImpl for AnyhowContext {
141    fn kind(&self) -> FrameKind<'_> {
142        FrameKind::Context(self)
143    }
144
145    fn as_any(&self) -> &dyn Any {
146        &self.0
147    }
148
149    fn as_any_mut(&mut self) -> &mut dyn Any {
150        &mut self.0
151    }
152
153    #[cfg(nightly)]
154    #[inline]
155    fn provide<'a>(&'a self, request: &mut Request<'a>) {
156        Context::provide(self, request);
157    }
158}
159
160#[cfg(feature = "eyre")]
161struct EyreContext(eyre::Report);
162
163#[cfg(feature = "eyre")]
164impl fmt::Debug for EyreContext {
165    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
166        fmt::Debug::fmt(&self.0, fmt)
167    }
168}
169
170#[cfg(feature = "eyre")]
171impl fmt::Display for EyreContext {
172    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
173        fmt::Display::fmt(&self.0, fmt)
174    }
175}
176
177#[cfg(feature = "eyre")]
178impl Context for EyreContext {
179    #[cfg(nightly)]
180    #[inline]
181    fn provide<'a>(&'a self, request: &mut Request<'a>) {
182        Error::provide(self.0.as_ref() as &dyn Error, request);
183    }
184}
185
186#[cfg(feature = "eyre")]
187impl FrameImpl for EyreContext {
188    fn kind(&self) -> FrameKind<'_> {
189        FrameKind::Context(self)
190    }
191
192    fn as_any(&self) -> &dyn Any {
193        &self.0
194    }
195
196    fn as_any_mut(&mut self) -> &mut dyn Any {
197        &mut self.0
198    }
199
200    #[cfg(nightly)]
201    #[inline]
202    fn provide<'a>(&'a self, request: &mut Request<'a>) {
203        Context::provide(self, request);
204    }
205}
206
207impl Frame {
208    /// Creates a frame from a [`Context`].
209    pub(crate) fn from_context<C>(context: C, sources: Box<[Self]>) -> Self
210    where
211        C: Context,
212    {
213        Self {
214            frame: Box::new(ContextFrame { context }),
215            sources,
216        }
217    }
218
219    /// Creates a frame from an attachment.
220    pub(crate) fn from_attachment<A>(attachment: A, sources: Box<[Self]>) -> Self
221    where
222        A: Send + Sync + 'static,
223    {
224        Self {
225            frame: Box::new(AttachmentFrame { attachment }),
226            sources,
227        }
228    }
229
230    /// Creates a frame from an attachment which implements [`Debug`] and [`Display`].
231    ///
232    /// [`Debug`]: core::fmt::Debug
233    /// [`Display`]: core::fmt::Display
234    pub(crate) fn from_printable_attachment<A>(attachment: A, sources: Box<[Self]>) -> Self
235    where
236        A: fmt::Display + fmt::Debug + Send + Sync + 'static,
237    {
238        Self {
239            frame: Box::new(PrintableAttachmentFrame { attachment }),
240            sources,
241        }
242    }
243
244    /// Creates a frame from an [`anyhow::Error`].
245    #[cfg(feature = "anyhow")]
246    pub(crate) fn from_anyhow(error: anyhow::Error, sources: Box<[Self]>) -> Self {
247        Self {
248            frame: Box::new(AnyhowContext(error)),
249            sources,
250        }
251    }
252
253    /// Creates a frame from an [`eyre::Report`].
254    #[cfg(feature = "eyre")]
255    pub(crate) fn from_eyre(report: eyre::Report, sources: Box<[Self]>) -> Self {
256        Self {
257            frame: Box::new(EyreContext(report)),
258            sources,
259        }
260    }
261}