Skip to main content

rootcause/report/
owned.rs

1use core::{
2    any::{Any, TypeId},
3    marker::PhantomData,
4};
5
6use rootcause_internals::{
7    RawReport,
8    handlers::{ContextFormattingStyle, FormattingFunction},
9};
10
11use crate::{
12    ReportConversion, ReportIter, ReportMut, ReportRef,
13    handlers::{self, ContextHandler},
14    markers::{
15        self, Cloneable, Dynamic, Local, Mutable, ReportOwnershipMarker, SendSync, Uncloneable,
16    },
17    report::iter::DowncastIterator,
18    report_attachment::ReportAttachment,
19    report_attachments::ReportAttachments,
20    report_collection::ReportCollection,
21    util::ErrorNoSourceWrapper,
22};
23
24/// FIXME: Once rust-lang/rust#132922 gets resolved, we can make the `raw` field
25/// an unsafe field and remove this module.
26mod limit_field_access {
27    use core::marker::PhantomData;
28
29    use rootcause_internals::{RawReport, RawReportMut, RawReportRef};
30
31    use crate::markers::{self, Dynamic, Mutable, SendSync};
32
33    /// An error report that contains a context, child reports, and attachments.
34    ///
35    /// [`Report`] is the main type for creating and working with error reports
36    /// in this library. It can contain a root context (typically an error),
37    /// zero or more child reports, and zero or more attachments.
38    ///
39    /// # Type Parameters
40    ///
41    /// [`Report`] has three type parameters that control its behavior:
42    ///
43    /// - **Context (`C`)**: The type of the root error or context (defaults to
44    ///   [`Dynamic`])
45    /// - **Ownership (`O`)**: Controls whether the report can be cloned
46    ///   - [`Mutable`]: Unique ownership, can modify but cannot clone (default)
47    ///   - [`Cloneable`]: Shared ownership via [`Arc`], can clone but cannot
48    ///     modify root
49    /// - **Thread Safety (`T`)**: Controls whether the report can be sent
50    ///   across threads
51    ///   - [`SendSync`]: Can be sent across threads (default, requires all data
52    ///     is [`Send`]+[`Sync`])
53    ///   - [`Local`]: Cannot be sent across threads (allows non-thread-safe
54    ///     data)
55    ///
56    /// # Common Usage
57    ///
58    /// The easiest way to create a [`Report`] is with the [`report!()`] macro:
59    ///
60    /// ```
61    /// # use rootcause::prelude::*;
62    /// let report: Report = report!("file missing");
63    /// println!("{report}");
64    /// ```
65    ///
66    /// You can add context and attachments using method chaining:
67    ///
68    /// ```
69    /// # use rootcause::prelude::*;
70    /// let report = report!("database query failed")
71    ///     .context("failed to fetch user data")
72    ///     .attach("user_id: 12345");
73    /// println!("{report}");
74    /// ```
75    ///
76    /// [`Arc`]: triomphe::Arc
77    /// [`Local`]: crate::markers::Local
78    /// [`Mutable`]: crate::markers::Mutable
79    /// [`Cloneable`]: crate::markers::Cloneable
80    /// [`SendSync`]: crate::markers::SendSync
81    /// [`report!()`]: crate::report!
82    #[repr(transparent)]
83    pub struct Report<
84        Context: ?Sized + 'static = Dynamic,
85        Ownership: 'static = Mutable,
86        ThreadSafety: 'static = SendSync,
87    > {
88        /// # Safety
89        ///
90        /// The following safety invariants are guaranteed to be upheld as long
91        /// as this struct exists:
92        ///
93        /// 1. `C` must either be a type bounded by `Sized`, or `Dynamic`.
94        /// 2. `O` must either be `Mutable` or `Cloneable`.
95        /// 3. `T` must either be `SendSync` or `Local`.
96        /// 4. If `C` is a `Sized` type: The context embedded in the report must
97        ///    be of type `C`
98        /// 5. If `O = Mutable`: This is the unique owner of the report. More
99        ///    specifically this means that the strong count of the underlying
100        ///    `triomphe::Arc` is exactly 1.
101        /// 6. If `O = Cloneable`: All other references to this report are
102        ///    compatible with shared ownership. Specifically there are no
103        ///    references with an assumption that the strong_count is `1`.
104        /// 7. All references to any sub-reports of this report are compatible
105        ///    with shared ownership. Specifically there are no references with
106        ///    an assumption that the strong_count is `1`.
107        /// 8. If `T = SendSync`: All contexts and attachments in the report and
108        ///    all sub-reports must be `Send+Sync`.
109        raw: RawReport,
110        _context: PhantomData<Context>,
111        _ownership: PhantomData<Ownership>,
112        _thread_safety: PhantomData<ThreadSafety>,
113    }
114
115    impl<C: ?Sized, O, T> Report<C, O, T> {
116        /// Creates a new [`Report`] from a [`RawReport`]
117        ///
118        /// # Safety
119        ///
120        /// The caller must ensure:
121        ///
122        /// 1. `C` must either be a type bounded by `Sized`, or `Dynamic`.
123        /// 2. `O` must either be `Mutable` or `Cloneable`.
124        /// 3. `T` must either be `SendSync` or `Local`.
125        /// 4. If `C` is a `Sized` type: The context embedded in the report must
126        ///    be of type `C`
127        /// 5. If `O = Mutable`: This is the unique owner of the report. More
128        ///    specifically this means that the strong count of the underlying
129        ///    `triomphe::Arc` is exactly 1.
130        /// 6. If `O = Cloneable`: All other references to this report are
131        ///    compatible with shared ownership. Specifically there are no
132        ///    references with an assumption that the strong_count is `1`.
133        /// 7. All references to any sub-reports of this report are compatible
134        ///    with shared ownership. Specifically there are no references with
135        ///    an assumption that the strong_count is `1`.
136        /// 8. If `T = SendSync`: All contexts and attachments in the report and
137        ///    all sub-reports must be `Send+Sync`.
138        #[must_use]
139        pub(crate) unsafe fn from_raw(raw: RawReport) -> Self {
140            // SAFETY: We must uphold the safety invariants of the raw field:
141            // 1. Guaranteed by the caller
142            // 2. Guaranteed by the caller
143            // 3. Guaranteed by the caller
144            // 4. Guaranteed by the caller
145            // 5. Guaranteed by the caller
146            // 6. Guaranteed by the caller
147            // 7. Guaranteed by the caller
148            // 8. Guaranteed by the caller
149            Self {
150                raw,
151                _context: PhantomData,
152                _ownership: PhantomData,
153                _thread_safety: PhantomData,
154            }
155        }
156
157        /// Consumes the [`Report`] and returns the inner [`RawReport`].
158        #[must_use]
159        pub(crate) fn into_raw(self) -> RawReport {
160            // SAFETY: We are destroying `self`, so we no longer
161            // need to uphold any safety invariants.
162            self.raw
163        }
164
165        /// Creates a lifetime-bound [`RawReportRef`] from the inner
166        /// [`RawReport`].
167        #[must_use]
168        pub(crate) fn as_raw_ref(&self) -> RawReportRef<'_> {
169            // SAFETY: We must uphold the safety invariants of the raw field:
170            // 1. Upheld as the type parameters do not change.
171            // 2. Upheld as the type parameters do not change.
172            // 3. Upheld as the type parameters do not change.
173            // 4. Trivially upheld, as no mutation occurs
174            // 5. The only way to break this would be to call `RawReportRef::clone_arc`, but
175            //    that method has a `safety` requirement that the caller must ensure that no
176            //    owners exist which are incompatible with shared ownership. Since `self` is
177            //    incompatible with shared ownership when `O=Mutable`, this cannot happen.
178            // 6. Trivially upheld, as no mutation occurs
179            // 7. Upheld, as this does not create any such references.
180            // 8. Trivially upheld, as no mutation occurs
181            let raw = &self.raw;
182
183            raw.as_ref()
184        }
185    }
186
187    impl<C: ?Sized, T> Report<C, markers::Mutable, T> {
188        /// Creates a lifetime-bound [`RawReportMut`] from the inner
189        /// [`RawReport`].
190        ///
191        /// # Safety
192        ///
193        /// The caller must ensure:
194        ///
195        /// 1. If `T = SendSync`, no objects are added to the report through
196        ///    this that are not `Send+Sync`
197        #[must_use]
198        pub(crate) unsafe fn as_raw_mut(&mut self) -> RawReportMut<'_> {
199            // SAFETY: We need to uphold the safety invariants of the raw field:
200            // 1. Upheld as the type parameters do not change.
201            // 2. Upheld as the type parameters do not change.
202            // 3. Upheld as the type parameters do not change.
203            // 4. While mutation of the context is possible through this reference, it is
204            //    not possible to change the type of the context. Therefore this invariant
205            //    is upheld.
206            // 5. The only way to break this would be to call `RawReportRef::clone_arc`, but
207            //    that method has a `safety` requirement that the caller must ensure that no
208            //    owners exist which are incompatible with shared ownership. Since `self` is
209            //    the unique owner, this cannot happen.
210            // 6. `O = Mutable`, so this is trivially upheld.
211            // 7. Upheld, as this does not create any such references.
212            // 8. The caller guarantees that the current report is not modified in an
213            //    incompatible way and it is not possible to mutate the sub-reports.
214            let raw = &mut self.raw;
215
216            // SAFETY:
217            // 1. This method is in an impl for `Report<C, Mutable, T>`, which means that we
218            //    can invoke our own safety invariant to show that this is indeed the unique
219            //    owner of the report.
220            unsafe { raw.as_mut() }
221        }
222    }
223}
224
225pub use limit_field_access::Report;
226
227impl<C: Sized, T> Report<C, Mutable, T> {
228    /// Creates a new [`Report`] with the given context.
229    ///
230    /// This method is generic over the thread safety marker `T`. The context
231    /// will use the [`handlers::Error`] handler for formatting.
232    ///
233    /// See also:
234    ///
235    /// - The [`report!()`] macro will also create a new [`Report`], but can
236    ///   auto-detect the thread safety marker and handler.
237    /// - [`Report::new_sendsync`] and [`Report::new_local`] are more
238    ///   restrictive variants of this function that might help avoid type
239    ///   inference issues.
240    /// - [`Report::new_custom`] also allows you to manually specify the
241    ///   handler.
242    ///
243    /// [`report!()`]: crate::report!
244    ///
245    /// # Examples
246    /// ```
247    /// # use rootcause::{prelude::*, markers::{SendSync, Mutable, Local}};
248    /// # #[derive(Debug)]
249    /// # struct MyError;
250    /// # impl core::error::Error for MyError {}
251    /// # impl core::fmt::Display for MyError { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { unimplemented!() }}
252    /// let report_sendsync: Report<MyError, Mutable, SendSync> = Report::new(MyError);
253    /// let report_local: Report<MyError, Mutable, Local> = Report::new(MyError);
254    /// ```
255    #[track_caller]
256    #[must_use]
257    pub fn new(context: C) -> Self
258    where
259        C: markers::ObjectMarkerFor<T> + core::error::Error,
260    {
261        Self::new_custom::<handlers::Error>(context)
262    }
263
264    /// Creates a new [`Report`] with the given context and handler.
265    ///
266    /// This method is generic over the thread safety marker `T`.
267    ///
268    /// If you're having trouble with type inference for the thread safety
269    /// parameter, consider using [`Report::new_sendsync_custom`] or
270    /// [`Report::new_local_custom`] instead.
271    ///
272    /// # Examples
273    /// ```
274    /// # use rootcause::{prelude::*, markers::{SendSync, Local}};
275    /// # #[derive(Debug)]
276    /// # struct MyError;
277    /// # impl core::error::Error for MyError {}
278    /// # impl core::fmt::Display for MyError { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { unimplemented!() }}
279    /// let report_sendsync: Report<MyError> = Report::new_custom::<handlers::Debug>(MyError);
280    /// let report_local: Report<MyError> = Report::new_custom::<handlers::Display>(MyError);
281    /// ```
282    #[track_caller]
283    #[must_use]
284    pub fn new_custom<H>(context: C) -> Self
285    where
286        C: markers::ObjectMarkerFor<T>,
287        H: ContextHandler<C>,
288    {
289        Self::from_parts::<H>(context, ReportCollection::new(), ReportAttachments::new())
290    }
291
292    /// Creates a new [`Report`] with the given context, children, and
293    /// attachments.
294    ///
295    /// This method processes hooks during report creation. If you want to skip
296    /// hook processing, use [`Report::from_parts_unhooked`] instead.
297    ///
298    /// # Examples
299    /// ```
300    /// # use rootcause::{prelude::*, report_collection::ReportCollection, report_attachments::ReportAttachments, markers::{SendSync}};
301    /// let report: Report<String, _, SendSync> = Report::from_parts::<handlers::Display>(
302    ///     "error".to_string(),
303    ///     ReportCollection::new(),
304    ///     ReportAttachments::new(),
305    /// );
306    /// ```
307    #[track_caller]
308    #[must_use]
309    pub fn from_parts<H>(
310        context: C,
311        children: ReportCollection<Dynamic, T>,
312        attachments: ReportAttachments<T>,
313    ) -> Self
314    where
315        C: markers::ObjectMarkerFor<T>,
316        H: ContextHandler<C>,
317    {
318        let mut report: Self = Self::from_parts_unhooked::<H>(context, children, attachments);
319        C::run_creation_hooks(report.as_mut().into_dynamic());
320        report
321    }
322
323    /// Creates a new [`Report`] with the given context, children, and
324    /// attachments without hook processing.
325    ///
326    /// This method skips hook processing during report creation. If you want
327    /// hooks to be processed, use [`Report::from_parts`] instead.
328    ///
329    /// # Examples
330    /// ```
331    /// # use rootcause::{prelude::*, report_collection::ReportCollection, report_attachments::ReportAttachments, markers::SendSync};
332    /// let report: Report<String, _, SendSync> = Report::from_parts_unhooked::<handlers::Display>(
333    ///     "error".to_string(),
334    ///     ReportCollection::new(),
335    ///     ReportAttachments::new(),
336    /// );
337    /// ```
338    #[track_caller]
339    #[must_use]
340    pub fn from_parts_unhooked<H>(
341        context: C,
342        children: ReportCollection<Dynamic, T>,
343        attachments: ReportAttachments<T>,
344    ) -> Self
345    where
346        C: markers::ObjectMarkerFor<T>,
347        H: ContextHandler<C>,
348    {
349        let raw = RawReport::new::<C, H>(context, children.into_raw(), attachments.into_raw());
350
351        // SAFETY:
352        // 1. `C` is bounded by `Sized`, so this is upheld.
353        // 2. `O=Mutable`, so this is trivially upheld.
354        // 3. `C` is bounded by `markers::ObjectMarkerFor<T>` and this can only be
355        //    implemented for `T=Local` and `T=SendSync`, so this is
356        //   upheld.
357        // 4. We just created the report and the `C` does indeed match.
358        // 5. We just created the report and we are the unique owner.
359        // 6. `O=Mutable`, so this is trivially upheld.
360        // 7. This is guaranteed by the invariants of the `ReportCollection` we used to
361        //    create the raw report.
362        // 8. If `T=Local`, then this is trivially true. If `T=SendSync`, then we have
363        //    `C: ObjectMarkerFor<SendSync>`, so the context is `Send+Sync`.
364        //    Additionally the invariants of the `ReportCollection` and
365        //    `ReportAttachments` guarantee that the children and attachments are
366        //    `Send+Sync` as well.
367        unsafe {
368            // @add-unsafe-context: ReportCollection
369            // @add-unsafe-context: ReportAttachments
370            // @add-unsafe-context: markers::ObjectMarkerFor
371            Report::<C, Mutable, T>::from_raw(raw)
372        }
373    }
374
375    /// Decomposes the [`Report`] into its constituent parts.
376    ///
377    /// Returns a tuple containing the context, the children collection and the
378    /// attachments collection in that order. This is the inverse operation
379    /// of [`Report::from_parts`] and [`Report::from_parts_unhooked`].
380    ///
381    /// This method can be useful when you need to:
382    /// - Extract and modify individual components of a report
383    /// - Rebuild a report with different components
384    /// - Transfer components between different reports
385    /// - Perform custom processing on specific parts
386    ///
387    /// Note that to exactly reconstruct the original report, you will also need
388    /// to use the same handler as was used for the original report.
389    ///
390    /// # Examples
391    /// ```
392    /// # use rootcause::{prelude::*, report_collection::ReportCollection, report_attachments::ReportAttachments};
393    /// // Create a report with some children and attachments
394    /// let mut report: Report<String> = Report::from_parts::<handlers::Display>(
395    ///     "main error".to_string(),
396    ///     ReportCollection::new(),
397    ///     ReportAttachments::new(),
398    /// );
399    ///
400    /// // Add some content
401    /// let child_report = report!("child error").into_dynamic().into_cloneable();
402    /// report.children_mut().push(child_report);
403    /// report.attachments_mut().push("debug info".into());
404    ///
405    /// // Decompose into parts
406    /// let (context, children, attachments) = report.into_parts();
407    ///
408    /// assert_eq!(context, "main error");
409    /// assert_eq!(children.len(), 1);
410    /// assert!(attachments.len() >= 1); // "debug info" + potential automatic attachments
411    ///
412    /// // Can rebuild with the same or different parts
413    /// let rebuilt: Report<String> = Report::from_parts::<handlers::Display>(
414    ///     context,
415    ///     children,
416    ///     attachments,
417    /// );
418    /// ```
419    #[must_use]
420    pub fn into_parts(self) -> (C, ReportCollection<Dynamic, T>, ReportAttachments<T>) {
421        let raw = self.into_raw();
422
423        // SAFETY:
424        // 1. This is guaranteed by the invariants of this type.
425        // 2. Since `O=Mutable` and we are consuming `self`, then this is guaranteed to
426        //    be the unique owner of the report. We also know that there are no other
427        //    references such as `ReportRef` or `ReportMut` active, as those would
428        //    require a borrow of `self`.
429        let (context, children, attachments) = unsafe { raw.into_parts() };
430
431        // SAFETY:
432        // 1. `C=Dynamic` for the created collection, so this is trivially true.
433        // 2. The invariants of this type guarantee that `T` is either `Local` or
434        //    `SendSync`.
435        // 3. `C=Dynamic` for the created collection, so this is trivially true.
436        // 4. This is guaranteed by the invariants of this type.
437        // 5. If `T=Local`, then this is trivially true. If `T=SendSync`, then this is
438        //    guaranteed by the invariants of this type.
439        let children = unsafe { ReportCollection::<Dynamic, T>::from_raw(children) };
440
441        // SAFETY:
442        // 1. `T` is guaranteed to either be `Local` or `SendSync` by the invariants of
443        //    this type.
444        // 2. If `T=Local`, then this is trivially true. If `T=SendSync`, then this is
445        //    guaranteed by the invariants of this type.
446        let attachments = unsafe { ReportAttachments::<T>::from_raw(attachments) };
447
448        (context, children, attachments)
449    }
450
451    /// Extracts and returns the context value from the [`Report`].
452    ///
453    /// This is a convenience method that consumes the [`Report`] and returns
454    /// only the context, discarding the children and attachments. It's
455    /// equivalent to calling `report.into_parts().0`.
456    ///
457    /// This method can be useful when:
458    /// - You only need the underlying error or context value
459    /// - Converting from a [`Report`] back to the original error type
460    /// - Extracting context for logging or forwarding to other systems
461    /// - Implementing error conversion traits
462    ///
463    /// # Examples
464    /// ```
465    /// # use rootcause::prelude::*;
466    /// #[derive(Debug, PartialEq, Clone)]
467    /// struct MyError {
468    ///     message: String,
469    ///     code: u32,
470    /// }
471    ///
472    /// impl std::fmt::Display for MyError {
473    ///     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
474    ///         write!(f, "Error {}: {}", self.code, self.message)
475    ///     }
476    /// }
477    ///
478    /// // Create a report with a custom error context
479    /// let original_error = MyError {
480    ///     message: "database connection failed".to_string(),
481    ///     code: 500,
482    /// };
483    /// let report: Report<MyError> = report!(original_error.clone());
484    ///
485    /// // Extract just the context, discarding report structure
486    /// let extracted_error = report.into_current_context();
487    /// assert_eq!(extracted_error, original_error);
488    /// assert_eq!(extracted_error.code, 500);
489    /// assert_eq!(extracted_error.message, "database connection failed");
490    /// ```
491    #[must_use]
492    pub fn into_current_context(self) -> C {
493        self.into_parts().0
494    }
495
496    /// Returns a mutable reference to the current context.
497    ///
498    /// # Examples
499    /// ```
500    /// use rootcause::prelude::*;
501    /// let mut report: Report<String> = report!(String::from("An error occurred"));
502    /// let context: &mut String = report.current_context_mut();
503    /// context.push_str(" and that's bad");
504    /// ```
505    #[must_use]
506    pub fn current_context_mut(&mut self) -> &mut C {
507        self.as_mut().into_current_context_mut()
508    }
509
510    /// Transforms the context type by applying a function, preserving report
511    /// structure.
512    ///
513    /// Converts the context type in-place without creating new nodes. Children,
514    /// attachments, and hook data (backtraces, locations) are preserved.
515    ///
516    /// # Examples
517    ///
518    /// ```
519    /// # use rootcause::prelude::*;
520    /// # #[derive(Debug)]
521    /// # struct LibError;
522    /// # impl std::fmt::Display for LibError {
523    /// #     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "lib error") }
524    /// # }
525    /// # #[derive(Debug)]
526    /// enum AppError {
527    ///     Lib(LibError)
528    /// }
529    /// # impl std::fmt::Display for AppError {
530    /// #     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "app error") }
531    /// # }
532    ///
533    /// let lib_report: Report<LibError> = report!(LibError);
534    /// let app_report: Report<AppError> = lib_report.context_transform(AppError::Lib);
535    /// ```
536    ///
537    /// # See Also
538    ///
539    /// - [`ContextTransformNestedExt::context_transform_nested`] - Wraps original as preformatted child
540    /// - [`context()`](Report::context) - Adds new parent context
541    /// - [`context_to()`](Report::context_to) - Uses
542    ///   [`ReportConversion`](crate::ReportConversion) trait
543    /// - [`examples/context_methods.rs`] - Comparison guide
544    ///
545    /// [`ContextTransformNestedExt::context_transform_nested`]: https://docs.rs/rootcause-preformat/latest/rootcause_preformat/trait.ContextTransformNestedExt.html#method.context_transform_nested
546    /// [`examples/context_methods.rs`]: https://github.com/rootcause-rs/rootcause/blob/main/examples/context_methods.rs
547    #[track_caller]
548    pub fn context_transform<F, D>(self, f: F) -> Report<D, Mutable, T>
549    where
550        F: FnOnce(C) -> D,
551        D: markers::ObjectMarkerFor<T> + core::fmt::Display + core::fmt::Debug,
552    {
553        let (context, children, attachments) = self.into_parts();
554        let new_context = f(context);
555
556        Report::from_parts_unhooked::<handlers::Display>(new_context, children, attachments)
557    }
558}
559
560impl<C: ?Sized, T> Report<C, Mutable, T> {
561    /// Returns a mutable reference to the report.
562    ///
563    /// # Examples
564    /// ```
565    /// use rootcause::{ReportMut, prelude::*};
566    /// let mut report: Report = report!("error message");
567    /// let report_mut: ReportMut<'_> = report.as_mut();
568    /// ```
569    #[must_use]
570    pub fn as_mut(&mut self) -> ReportMut<'_, C, T> {
571        // SAFETY:
572        // 1. If `T=Local`, then this is trivially true. If `T=SendSync`, then we are
573        //    not allowed to mutate the returned raw report in a way that adds
574        //    non-`Send+Sync` objects. However the invariants of the created `ReportMut`
575        //    guarantee that no such mutation can occur.
576        let raw = unsafe { self.as_raw_mut() };
577
578        // SAFETY:
579        // 1. This is guaranteed by the invariants of this type.
580        // 2. This is guaranteed by the invariants of this type.
581        // 3. This is guaranteed by the invariants of this type.
582        // 4. This is guaranteed by the invariants of this type.
583        // 5. This is guaranteed by the invariants of this type.
584        // 6. This is guaranteed by the invariants of this type.
585        // 7. We have a `&mut self`. This means that there are no other borrows active
586        //    to `self`. We also know that this is the unique owner of the report, so
587        //    there are no other references to it through different ownership. This
588        //    means that there are no other references to this report at all, so there
589        //    cannot be any incompatible references.
590        unsafe { ReportMut::from_raw(raw) }
591    }
592
593    /// Adds a new attachment to the [`Report`].
594    ///
595    /// This is a convenience method used for chaining method calls; it consumes
596    /// the [`Report`] and returns it.
597    ///
598    /// If you want more direct control over the attachments, you can use the
599    /// [`Report::attachments_mut`].
600    ///
601    /// # Examples
602    /// ```
603    /// # use rootcause::prelude::*;
604    /// let report: Report = report!("error message");
605    /// let with_attachment = report.attach("additional info");
606    /// ```
607    #[must_use]
608    pub fn attach<A>(mut self, attachment: A) -> Self
609    where
610        A: markers::ObjectMarkerFor<T> + core::fmt::Display + core::fmt::Debug,
611    {
612        self.attachments_mut()
613            .push(ReportAttachment::new(attachment).into_dynamic());
614        self
615    }
616
617    /// Adds a new attachment to the [`Report`].
618    ///
619    /// This is a convenience method used for chaining method calls; it consumes
620    /// the [`Report`] and returns it.
621    ///
622    /// If you want more direct control over the attachments, you can use the
623    /// [`Report::attachments_mut`].
624    ///
625    /// # Examples
626    /// ```
627    /// # use rootcause::prelude::*;
628    /// let report: Report = report!("error message");
629    /// let with_attachment = report.attach_custom::<handlers::Display, _>("info");
630    /// ```
631    #[must_use]
632    pub fn attach_custom<H, A>(mut self, attachment: A) -> Self
633    where
634        A: markers::ObjectMarkerFor<T>,
635        H: handlers::AttachmentHandler<A>,
636    {
637        self.attachments_mut()
638            .push(ReportAttachment::new_custom::<H>(attachment).into_dynamic());
639        self
640    }
641
642    /// Returns a mutable reference to the child reports.
643    ///
644    /// # Examples
645    /// ```
646    /// # use rootcause::{prelude::*, report_collection::ReportCollection};
647    /// let mut report: Report = report!("error message");
648    /// let children_mut: &mut ReportCollection = report.children_mut();
649    /// ```
650    #[must_use]
651    pub fn children_mut(&mut self) -> &mut ReportCollection<Dynamic, T> {
652        self.as_mut().into_children_mut()
653    }
654
655    /// Returns a mutable reference to the attachments.
656    ///
657    /// # Examples
658    /// ```
659    /// # use rootcause::{prelude::*, report_attachments::ReportAttachments};
660    /// let mut report: Report = report!("error message");
661    /// let attachments_mut: &mut ReportAttachments = report.attachments_mut();
662    /// ```
663    #[must_use]
664    pub fn attachments_mut(&mut self) -> &mut ReportAttachments<T> {
665        self.as_mut().into_attachments_mut()
666    }
667
668    /// Returns a [`&mut dyn Any`](Any) view of the current context.
669    ///
670    /// This works whether the context type `C` is known at compile time or
671    /// erased to [`Dynamic`]. The returned reference can be downcast using
672    /// `<dyn Any>::downcast_mut`.
673    ///
674    /// [`Dynamic`]: crate::markers::Dynamic
675    ///
676    /// # Examples
677    /// ```
678    /// # use rootcause::prelude::*;
679    /// # use core::any::Any;
680    /// let mut report: Report<String> = report!(String::from("An error occurred"));
681    /// let any: &mut dyn Any = report.current_context_as_any_mut();
682    /// if let Some(s) = any.downcast_mut::<String>() {
683    ///     s.push_str(" and that's bad");
684    /// }
685    /// ```
686    #[must_use]
687    pub fn current_context_as_any_mut(&mut self) -> &mut (dyn Any + 'static) {
688        self.as_mut().into_current_context_as_any_mut()
689    }
690}
691
692impl<C: ?Sized, O, T> Report<C, O, T> {
693    /// Creates a new [`Report`] with the given context and sets the current
694    /// report as a child of the new report.
695    ///
696    /// The new context will use the [`handlers::Display`] handler to format the
697    /// context.
698    ///
699    /// This is a convenience method used for chaining method calls; it consumes
700    /// the [`Report`] and returns it.
701    ///
702    /// If you want a different context handler, you can use
703    /// [`Report::context_custom`].
704    ///
705    /// If you want to more directly control the allocation of the new report,
706    /// you can use [`Report::from_parts`], which is the underlying method
707    /// used to implement this method.
708    ///
709    /// # Examples
710    /// ```
711    /// # use rootcause::prelude::*;
712    /// let report: Report = report!("initial error");
713    /// let contextual_report: Report<&str> = report.context("additional context");
714    /// ```
715    #[track_caller]
716    #[must_use]
717    pub fn context<D>(self, context: D) -> Report<D, Mutable, T>
718    where
719        D: markers::ObjectMarkerFor<T> + core::fmt::Display + core::fmt::Debug,
720    {
721        self.context_custom::<handlers::Display, _>(context)
722    }
723
724    /// Creates a new [`Report`] with the given context and sets the current
725    /// report as a child of the new report.
726    ///
727    /// This is a convenience method used for chaining method calls; it consumes
728    /// the [`Report`] and returns it.
729    ///
730    /// If you want to more directly control the allocation of the new report,
731    /// you can use [`Report::from_parts`], which is the underlying method
732    /// used to implement this method.
733    ///
734    /// # Examples
735    /// ```
736    /// # use rootcause::prelude::*;
737    /// let report: Report = report!("initial error");
738    /// let contextual_report: Report<&str> = report.context_custom::<handlers::Debug, _>("context");
739    /// ```
740    #[track_caller]
741    #[must_use]
742    pub fn context_custom<H, D>(self, context: D) -> Report<D, Mutable, T>
743    where
744        D: markers::ObjectMarkerFor<T>,
745        H: ContextHandler<D>,
746    {
747        Report::from_parts::<H>(
748            context,
749            ReportCollection::from([self.into_dynamic().into_cloneable()]),
750            ReportAttachments::<T>::new(),
751        )
752    }
753
754    /// Converts this report to a different context type using
755    /// [`ReportConversion`].
756    ///
757    /// Implement [`ReportConversion`] once to define conversion logic, then use
758    /// [`context_to`](Self::context_to) at call sites. Useful for consistent
759    /// error type coercion across your codebase, especially when integrating
760    /// with external libraries. You typically need to specify the target type
761    /// (`::<Type>`).
762    ///
763    /// See also: [`context_transform`](Self::context_transform) for direct
764    /// conversion, `context_transform_nested` (in the
765    /// [`rootcause-preformat`](https://docs.rs/rootcause-preformat) crate) for
766    /// wrapping, [`examples/thiserror_interop.rs`] for integration patterns.
767    ///
768    /// [`examples/thiserror_interop.rs`]: https://github.com/rootcause-rs/rootcause/blob/main/examples/thiserror_interop.rs
769    ///
770    /// # Examples
771    ///
772    /// ```
773    /// # use rootcause::{ReportConversion, markers::Mutable, prelude::*};
774    /// # #[derive(Debug)]
775    /// enum AppError { Parse }
776    /// # impl std::fmt::Display for AppError {
777    /// #     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "error") }
778    /// # }
779    /// impl<T> ReportConversion<std::num::ParseIntError, Mutable, T> for AppError
780    ///   where AppError: markers::ObjectMarkerFor<T>
781    /// {
782    ///     fn convert_report(report: Report<std::num::ParseIntError, Mutable, T>) -> Report<Self, Mutable, T>
783    ///     {
784    ///         report.context(AppError::Parse)
785    ///     }
786    /// }
787    /// // After implementing ReportConversion, use at call sites:
788    /// let result: Result<i32, Report<AppError>> = "abc".parse::<i32>().context_to();
789    /// ```
790    #[track_caller]
791    #[must_use]
792    pub fn context_to<D: ReportConversion<C, O, T>>(self) -> Report<D, Mutable, T> {
793        D::convert_report(self)
794    }
795
796    /// Returns a reference to the child reports.
797    ///
798    /// # Examples
799    /// ```
800    /// # use rootcause::{prelude::*, report_collection::ReportCollection};
801    /// let report: Report = report!("error message");
802    /// let children: &ReportCollection = report.children();
803    /// assert_eq!(children.len(), 0); // The report has just been created, so it has no children
804    /// ```
805    #[must_use]
806    pub fn children(&self) -> &ReportCollection<Dynamic, T> {
807        self.as_uncloneable_ref().children()
808    }
809
810    /// Returns a reference to the attachments.
811    ///
812    /// # Examples
813    /// ```
814    /// # use rootcause::{prelude::*, report_attachments::ReportAttachments};
815    /// let report: Report = report!("error message");
816    /// let attachments: &ReportAttachments = report.attachments();
817    /// ```
818    #[must_use]
819    pub fn attachments(&self) -> &ReportAttachments<T> {
820        self.as_uncloneable_ref().attachments()
821    }
822
823    /// Changes the context type of the [`Report`] to [`Dynamic`].
824    ///
825    /// Calling this method is equivalent to calling `report.into()`, however
826    /// this method has been restricted to only change the context mode to
827    /// [`Dynamic`].
828    ///
829    /// This method can be useful to help with type inference or to improve code
830    /// readability, as it more clearly communicates intent.
831    ///
832    /// This method does not actually modify the report in any way. It only has
833    /// the effect of "forgetting" that the context actually has the type
834    /// `C`.
835    ///
836    /// To get back the report with a concrete `C` you can use the method
837    /// [`Report::downcast_report`].
838    ///
839    /// # Examples
840    /// ```
841    /// # use rootcause::{prelude::*, markers::Dynamic};
842    /// # struct MyError;
843    /// # let my_error = MyError;
844    /// let report: Report<MyError> = report!(my_error);
845    /// let dyn_report: Report<Dynamic> = report.into_dynamic();
846    /// ```
847    #[must_use]
848    pub fn into_dynamic(self) -> Report<Dynamic, O, T> {
849        let raw = self.into_raw();
850
851        // SAFETY:
852        // 1. `C=Dynamic`, so this is trivially true.
853        // 2. This is guaranteed by the invariants of this type.
854        // 3. This is guaranteed by the invariants of this type.
855        // 4. `C=Dynamic`, so this is trivially true.
856        // 5. This is guaranteed by the invariants of this type.
857        // 6. This is guaranteed by the invariants of this type.
858        // 7. This is guaranteed by the invariants of this type.
859        // 8. This is guaranteed by the invariants of this type.
860        unsafe {
861            // @add-unsafe-context: Dynamic
862            Report::<Dynamic, O, T>::from_raw(raw)
863        }
864    }
865
866    /// Changes the ownership of the [`Report`] to [`Cloneable`].
867    ///
868    /// Calling this method is equivalent to calling `report.into()`, however
869    /// this method has been restricted to only change the ownership mode to
870    /// [`Cloneable`].
871    ///
872    /// This method can be useful to help with type inference or to improve code
873    /// readability, as it more clearly communicates intent.
874    ///
875    /// This method does not actually modify the report in any way. It only has
876    /// the effect of "forgetting" that the [`Report`] only has a single
877    /// owner.
878    ///
879    /// After calling this method, you can clone the [`Report`], but you can no
880    /// longer add attachments to the [`Report`] or otherwise modify the
881    /// root node.
882    ///
883    /// To get back a [`Mutable`] you need to either:
884    /// - Allocate a new root node using e.g. [`Report::context`].
885    /// - If there is a single unique owner of the report, you can use
886    ///   [`Report::try_into_mutable`].
887    /// - Preformat the root node using [`PreformatReportExt::preformat`].
888    ///
889    /// [`PreformatReportExt::preformat`]: https://docs.rs/rootcause-preformat/latest/rootcause_preformat/trait.PreformatReportExt.html#method.preformat
890    ///
891    /// # Examples
892    /// ```
893    /// # use rootcause::{prelude::*, markers::{Mutable, Cloneable}};
894    /// # let my_error = "error message";
895    /// let report: Report<_, Mutable> = report!(my_error);
896    /// let cloneable_report: Report<_, Cloneable> = report.into_cloneable();
897    /// let cloned = cloneable_report.clone();
898    /// ```
899    #[must_use]
900    pub fn into_cloneable(self) -> Report<C, Cloneable, T> {
901        let raw = self.into_raw();
902
903        // SAFETY:
904        // 1. This is guaranteed by the invariants of `self`.
905        // 2. `O=Cloneable`, so this is trivially true.
906        // 3. This is guaranteed by the invariants of `self`.
907        // 4. This is guaranteed by the invariants of `self`.
908        // 5. `O=Cloneable`, so this is trivially true.
909        // 6. If the ownership of `self` is already `Cloneable`, then this is guaranteed
910        //    by the invariants of `self`. If the ownership of `self` is `Mutable`, then
911        //    the invariants of `self` guarantee that we are the only owner and we are
912        //    consuming `self` in this method, so there are no other owners.
913        // 7. This is guaranteed by the invariants of `self`.
914        // 8. This is guaranteed by the invariants of `self`.
915        unsafe { Report::<C, Cloneable, T>::from_raw(raw) }
916    }
917
918    /// Changes the thread safety mode of the [`Report`] to [`Local`].
919    ///
920    /// Calling this method is equivalent to calling `report.into()`, however
921    /// this method has been restricted to only change the thread safety
922    /// mode to [`Local`].
923    ///
924    /// This method can be useful to help with type inference or to improve code
925    /// readability, as it more clearly communicates intent.
926    ///
927    /// This method does not actually modify the report in any way. It only has
928    /// the effect of "forgetting" that all objects in the [`Report`] might
929    /// actually be [`Send`] and [`Sync`].
930    ///
931    /// After calling this method, you can add objects to the [`Report`] that
932    /// are neither [`Send`] nor [`Sync`], but the report itself will no
933    /// longer be [`Send`]+[`Sync`].
934    ///
935    /// # Examples
936    /// ```
937    /// # use rootcause::{prelude::*, markers::{Local, SendSync}};
938    /// # let my_error = "error message";
939    /// let report: Report<_, _, SendSync> = report!(my_error);
940    /// let local_report: Report<_, _, Local> = report.into_local();
941    /// ```
942    #[must_use]
943    pub fn into_local(self) -> Report<C, O, Local> {
944        let raw = self.into_raw();
945
946        // SAFETY:
947        // 1. This is guaranteed by the invariants of this type.
948        // 2. This is guaranteed by the invariants of this type.
949        // 3. `T=Local`, so this is trivially upheld.
950        // 4. This is guaranteed by the invariants of this type.
951        // 5. This is guaranteed by the invariants of this type.
952        // 6. This is guaranteed by the invariants of this type.
953        // 7. This is guaranteed by the invariants of this type.
954        // 8. `T=Local`, so this is trivially true.
955        unsafe { Report::<C, O, Local>::from_raw(raw) }
956    }
957
958    /// Checks if there is only a single unique owner of the root node of the
959    /// [`Report`].
960    ///
961    /// If there is only a single unique owner, this method
962    /// marks the current [`Report`] as [`Mutable`] and returns `Ok`,
963    /// otherwise it returns `Err` with the original [`Report`].
964    ///
965    /// This method does not actually modify the report in any way. It only has
966    /// the effect of checking for unique ownership and returns the same
967    /// report (with different type parameters) no matter the outcome of the
968    /// check.
969    ///
970    /// # Examples
971    /// ```
972    /// # use rootcause::{prelude::*, markers::{Mutable, Cloneable}};
973    /// # let some_report = report!("error message").into_cloneable();
974    /// let cloneable: Report<_, Cloneable> = some_report;
975    /// match cloneable.try_into_mutable() {
976    ///     Ok(mutable) => println!("Converted to mutable"),
977    ///     Err(cloneable) => println!("Still cloneable"),
978    /// }
979    /// ```
980    pub fn try_into_mutable(self) -> Result<Report<C, Mutable, T>, Report<C, O, T>> {
981        if self.strong_count() == 1 {
982            let raw = self.into_raw();
983
984            // SAFETY:
985            // 1. This is guaranteed by the invariants of this type.
986            // 2. `O=Mutable`, so this is trivially true.
987            // 3. This is guaranteed by the invariants of this type.
988            // 4. This is guaranteed by the invariants of this type.
989            // 5. We just checked that the strong count is `1`, and we are taking ownership
990            //    of `self`, so we are the unique owner.
991            // 6. `O=Mutable`, so this is trivially upheld.
992            // 7. This is guaranteed by the invariants of this type.
993            // 8. This is guaranteed by the invariants of this type.
994            let report = unsafe { Report::<C, Mutable, T>::from_raw(raw) };
995            Ok(report)
996        } else {
997            Err(self)
998        }
999    }
1000
1001    pub(crate) fn as_uncloneable_ref(&self) -> ReportRef<'_, C, Uncloneable, T> {
1002        let raw = self.as_raw_ref();
1003
1004        // SAFETY:
1005        // 1. This is guaranteed by the invariants of this type.
1006        // 2. `O=Uncloneable`, so this is trivially true.
1007        // 3. This is guaranteed by the invariants of this type.
1008        // 4. This is guaranteed by the invariants of this type.
1009        // 5. `O=Uncloneable`, so this is trivially true.
1010        // 6. This is guaranteed by the invariants of this type.
1011        // 7. This is guaranteed by the invariants of this type.
1012        unsafe {
1013            // @add-unsafe-context: markers::ReportOwnershipMarker
1014            ReportRef::<C, Uncloneable, T>::from_raw(raw)
1015        }
1016    }
1017
1018    /// Returns an immutable reference to the report.
1019    ///
1020    /// # Examples
1021    /// ```
1022    /// # use rootcause::{prelude::*, ReportRef, markers::{Cloneable, Mutable, Uncloneable}};
1023    /// let report: Report<_, Mutable> = report!("error message");
1024    /// let report_ref: ReportRef<'_, _, Uncloneable> = report.as_ref();
1025    ///
1026    /// let report: Report<_, Cloneable> = report!("error message").into_cloneable();
1027    /// let report_ref: ReportRef<'_, _, Cloneable> = report.as_ref();
1028    /// ```
1029    #[must_use]
1030    pub fn as_ref(&self) -> ReportRef<'_, C, O::RefMarker, T>
1031    where
1032        O: markers::ReportOwnershipMarker,
1033    {
1034        let raw = self.as_raw_ref();
1035
1036        // SAFETY:
1037        // 1. This is guaranteed by the invariants of this type.
1038        // 2. If the ownership of `self` is `Mutable`, then the `O=Uncloneable`, which
1039        //    means that this is trivially true. On the other hand, if the ownership of
1040        //    `self` is `Cloneable`, then the `O=Cloneable`, which is also trivially
1041        //    true.
1042        // 3. This is guaranteed by the invariants of this type.
1043        // 4. This is guaranteed by the invariants of this type.
1044        // 5. If the ownership of `self` is `Mutable`, then the `O=Uncloneable`, which
1045        //    means that this is trivially true. On the other hand, if the ownership of
1046        //    `self` is `Cloneable`, then the `O=Cloneable`. However in that case, the
1047        //    invariants of this type guarantee that all references are compatible.
1048        // 6. This is guaranteed by the invariants of this type.
1049        // 7. This is guaranteed by the invariants of this type.
1050        unsafe {
1051            // @add-unsafe-context: markers::ReportOwnershipMarker
1052            ReportRef::<C, O::RefMarker, T>::from_raw(raw)
1053        }
1054    }
1055
1056    /// Returns an iterator over the complete report hierarchy including this
1057    /// report.
1058    ///
1059    /// The iterator visits reports in a depth-first order: it first visits the
1060    /// current report, then recursively visits each child report and all of
1061    /// their descendants before moving to the next sibling. Unlike
1062    /// [`Report::iter_sub_reports`], this method includes the report on
1063    /// which it was called as the first item in the iteration.
1064    ///
1065    /// The ownership marker of the returned iterator references matches the
1066    /// ownership of this report. For mutable reports, the references may
1067    /// not be cloneable, which can limit how you can use them. If you need
1068    /// cloneable references, consider using [`Report::iter_sub_reports`]
1069    /// instead, which only iterates over children but guarantees
1070    /// cloneable references.
1071    ///
1072    /// See also: [`Report::iter_sub_reports`] for iterating only over child
1073    /// reports with cloneable references.
1074    ///
1075    /// # Examples
1076    /// ```
1077    /// # use rootcause::prelude::*;
1078    /// // Create base reports
1079    /// let error1: Report = report!("error 1");
1080    /// let error2: Report = report!("error 2");
1081    ///
1082    /// // Build hierarchy using .context() which creates new nodes
1083    /// let with_context1 = error1.context("context for error 1");  // Creates new node with error1 as child
1084    /// let with_context2 = error2.context("context for error 2");  // Creates new node with error2 as child
1085    ///
1086    /// // Create root that contains both context nodes as children
1087    /// let mut root = report!("root error").context("context for root error");
1088    /// root.children_mut().push(with_context1.into_dynamic().into_cloneable());
1089    /// root.children_mut().push(with_context2.into_dynamic().into_cloneable());
1090    ///
1091    /// // At this point our report tree looks like this:
1092    /// // - context for root error
1093    /// //   - root error
1094    /// //   - context for error 1
1095    /// //     - error 1
1096    /// //   - context for error 2
1097    /// //     - error 2
1098    ///
1099    /// let all_reports: Vec<String> = root
1100    ///     .iter_reports()
1101    ///     .map(|report| report.format_current_context().to_string())
1102    ///     .collect();
1103    ///
1104    /// assert_eq!(all_reports[0], "context for root error");  // Current report is included
1105    /// assert_eq!(all_reports[1], "root error");
1106    /// assert_eq!(all_reports.len(), 6);
1107    /// ```
1108    pub fn iter_reports(&self) -> ReportIter<'_, O::RefMarker, T>
1109    where
1110        O: markers::ReportOwnershipMarker,
1111    {
1112        self.as_ref().iter_reports()
1113    }
1114
1115    /// Returns an iterator over child reports in the report hierarchy
1116    /// (excluding this report).
1117    ///
1118    /// The iterator visits reports in a depth-first order: it first visits the
1119    /// current report's children, then recursively visits each child report
1120    /// and all of their descendants before moving to the next sibling.
1121    /// Unlike [`Report::iter_reports`], this method does NOT include the
1122    /// report on which it was called - only its descendants.
1123    ///
1124    /// This method always returns cloneable report references, making it
1125    /// suitable for scenarios where you need to store or pass around the
1126    /// report references. This is different from [`Report::iter_reports`],
1127    /// which returns references that match the ownership marker of the
1128    /// current report and may not be cloneable for mutable reports.
1129    ///
1130    /// See also: [`Report::iter_reports`] for iterating over all reports
1131    /// including the current one.
1132    ///
1133    /// # Examples
1134    /// ```
1135    /// # use rootcause::{prelude::*, markers::Cloneable};
1136    /// // Create base reports
1137    /// let error1: Report = report!("error 1");
1138    /// let error2: Report = report!("error 2");
1139    ///
1140    /// // Build hierarchy using .context() which creates new nodes
1141    /// let with_context1 = error1.context("context for error 1");  // Creates new node with error1 as child
1142    /// let with_context2 = error2.context("context for error 2");  // Creates new node with error2 as child
1143    ///
1144    /// // Create root that contains both context nodes as children
1145    /// let mut root = report!("root error").context("context for root error");
1146    /// root.children_mut().push(with_context1.into_dynamic().into_cloneable());
1147    /// root.children_mut().push(with_context2.into_dynamic().into_cloneable());
1148    ///
1149    /// let sub_reports: Vec<String> = root
1150    ///     .iter_sub_reports()  // Note: using iter_sub_reports, not iter_reports
1151    ///     .map(|report| report.format_current_context().to_string())
1152    ///     .collect();
1153    ///
1154    /// // Current "root" report is NOT included in the results
1155    /// assert_eq!(sub_reports[0], "root error");
1156    /// assert_eq!(sub_reports[1], "context for error 1");
1157    /// assert_eq!(sub_reports.len(), 5);
1158    /// ```
1159    pub fn iter_sub_reports(&self) -> ReportIter<'_, Cloneable, T>
1160    where
1161        O: markers::ReportOwnershipMarker,
1162    {
1163        self.as_uncloneable_ref().iter_sub_reports()
1164    }
1165
1166    /// Returns the [`TypeId`] of the current context.
1167    ///
1168    /// # Examples
1169    /// ```
1170    /// # use rootcause::{prelude::*, markers::Dynamic};
1171    /// # use core::any::TypeId;
1172    /// # struct MyError;
1173    /// let report: Report<MyError> = report!(MyError);
1174    /// let type_id = report.current_context_type_id();
1175    /// assert_eq!(type_id, TypeId::of::<MyError>());
1176    ///
1177    /// let report: Report<Dynamic> = report.into_dynamic();
1178    /// let type_id = report.current_context_type_id();
1179    /// assert_eq!(type_id, TypeId::of::<MyError>());
1180    /// ```
1181    #[must_use]
1182    pub fn current_context_type_id(&self) -> TypeId {
1183        self.as_uncloneable_ref().current_context_type_id()
1184    }
1185
1186    /// Returns the [`core::any::type_name`] of the current context.
1187    ///
1188    /// # Examples
1189    /// ```
1190    /// # use rootcause::{prelude::*, markers::Dynamic};
1191    /// # use core::any::TypeId;
1192    /// # struct MyError;
1193    /// # let report = report!(MyError).into_cloneable();
1194    /// let report: Report<MyError> = report!(MyError);
1195    /// let type_name = report.current_context_type_name();
1196    /// assert_eq!(type_name, core::any::type_name::<MyError>());
1197    ///
1198    /// let report: Report<Dynamic> = report.into_dynamic();
1199    /// let type_name = report.current_context_type_name();
1200    /// assert_eq!(type_name, core::any::type_name::<MyError>());
1201    /// ```
1202    #[must_use]
1203    pub fn current_context_type_name(&self) -> &'static str {
1204        self.as_uncloneable_ref().current_context_type_name()
1205    }
1206
1207    /// Returns the [`TypeId`] of the handler used for the current context.
1208    ///
1209    /// This can be useful for debugging or introspection to understand which
1210    /// handler was used to format the context.
1211    ///
1212    /// # Examples
1213    /// ```
1214    /// # use rootcause::{prelude::*, markers::SendSync};
1215    /// # use core::any::TypeId;
1216    /// let report : Report<&'static str> = Report::new_custom::<handlers::Debug>("error message");
1217    /// let handler_type = report.current_context_handler_type_id();
1218    /// assert_eq!(handler_type, TypeId::of::<handlers::Debug>());
1219    /// ```
1220    #[must_use]
1221    pub fn current_context_handler_type_id(&self) -> TypeId {
1222        self.as_uncloneable_ref().current_context_handler_type_id()
1223    }
1224
1225    /// Returns a [`&dyn Any`](Any) view of the current context.
1226    ///
1227    /// This is the most general accessor for the current context: it works
1228    /// whether the context type `C` is known at compile time or erased to
1229    /// [`Dynamic`]. The returned reference can be downcast using
1230    /// `<dyn Any>::downcast_ref` and interoperates with
1231    /// any code that accepts `&dyn Any`.
1232    ///
1233    /// [`Dynamic`]: crate::markers::Dynamic
1234    ///
1235    /// # Examples
1236    /// ```
1237    /// # use rootcause::prelude::*;
1238    /// # use core::any::Any;
1239    /// # struct MyError;
1240    /// let report: Report<MyError> = report!(MyError);
1241    /// let any: &dyn Any = report.current_context_as_any();
1242    /// assert!(any.is::<MyError>());
1243    ///
1244    /// // Also works for Dynamic reports
1245    /// let report: Report = report.into_dynamic();
1246    /// let any: &dyn Any = report.current_context_as_any();
1247    /// assert!(any.is::<MyError>());
1248    /// ```
1249    #[must_use]
1250    pub fn current_context_as_any(&self) -> &(dyn Any + 'static) {
1251        self.as_uncloneable_ref().current_context_as_any()
1252    }
1253
1254    /// Returns the error source if the context implements [`Error`].
1255    ///
1256    /// [`Error`]: core::error::Error
1257    ///
1258    /// # Examples
1259    /// ```
1260    /// # use rootcause::prelude::*;
1261    /// # use core::any::TypeId;
1262    /// let report: Report = report!("error message");
1263    /// let source: Option<&dyn core::error::Error> = report.current_context_error_source();
1264    /// assert!(source.is_none()); // The context does not implement Error, so no source
1265    ///
1266    /// #[derive(Debug, thiserror::Error)]
1267    /// enum MyError {
1268    ///     #[error("Io error: {0}")]
1269    ///     Io(#[from] std::io::Error),
1270    ///     // ...
1271    /// }
1272    ///
1273    /// let report: Report<MyError> = report!(MyError::Io(std::io::Error::other("My inner error")));
1274    /// let source: Option<&dyn std::error::Error> = report.current_context_error_source();
1275    /// assert_eq!(format!("{}", source.unwrap()), "My inner error");
1276    /// ```
1277    #[must_use]
1278    pub fn current_context_error_source(&self) -> Option<&(dyn core::error::Error + 'static)> {
1279        self.as_uncloneable_ref().current_context_error_source()
1280    }
1281
1282    /// Formats the current context with hook processing.
1283    ///
1284    /// # Examples
1285    /// ```
1286    /// # use rootcause::prelude::*;
1287    /// let report: Report = report!("error message");
1288    /// let formatted = report.format_current_context();
1289    /// println!("{formatted}");
1290    /// ```
1291    #[must_use]
1292    pub fn format_current_context(&self) -> impl core::fmt::Display + core::fmt::Debug {
1293        self.as_uncloneable_ref().format_current_context()
1294    }
1295
1296    /// Formats the current context without hook processing.
1297    ///
1298    /// # Examples
1299    /// ```
1300    /// # use rootcause::prelude::*;
1301    /// let report: Report = report!("error message");
1302    /// let formatted = report.format_current_context_unhooked();
1303    /// println!("{formatted}");
1304    /// ```
1305    #[must_use]
1306    pub fn format_current_context_unhooked(&self) -> impl core::fmt::Display + core::fmt::Debug {
1307        self.as_uncloneable_ref().format_current_context_unhooked()
1308    }
1309
1310    /// Formats the entire report using a specific report formatting hook.
1311    ///
1312    /// This method allows you to format a report with a custom formatter
1313    /// without globally registering it. This is useful for:
1314    /// - One-off custom formatting
1315    /// - Testing different formatters
1316    /// - Using different formatters in different parts of your application
1317    ///
1318    /// Unlike the default [`Display`](core::fmt::Display) and
1319    /// [`Debug`](core::fmt::Debug) implementations which use the
1320    /// globally registered hook, this method uses the hook you provide
1321    /// directly.
1322    ///
1323    /// # Examples
1324    ///
1325    /// ```
1326    /// use rootcause::{hooks::builtin_hooks::report_formatter::DefaultReportFormatter, prelude::*};
1327    ///
1328    /// let report = report!("error message");
1329    ///
1330    /// // Format with ASCII-only output (no Unicode or ANSI colors)
1331    /// let formatted = report.format_with(&DefaultReportFormatter::ASCII);
1332    /// println!("{}", formatted);
1333    /// ```
1334    #[must_use]
1335    pub fn format_with<H>(&self, hook: &H) -> impl core::fmt::Display + core::fmt::Debug
1336    where
1337        H: crate::hooks::report_formatter::ReportFormatter,
1338    {
1339        self.as_uncloneable_ref().format_with(hook)
1340    }
1341
1342    /// Gets the preferred formatting style for the context with hook
1343    /// processing.
1344    ///
1345    /// # Arguments
1346    ///
1347    /// - `report_formatting_function`: Whether the report in which this context
1348    ///   will be embedded is being formatted using [`Display`] formatting or
1349    ///   [`Debug`]
1350    ///
1351    /// [`Display`]: core::fmt::Display
1352    /// [`Debug`]: core::fmt::Debug
1353    ///
1354    /// See also [`Report::preferred_context_formatting_style_unhooked`].
1355    ///
1356    /// # Examples
1357    /// ```
1358    /// # use rootcause::prelude::*;
1359    /// let report: Report = report!("error message");
1360    /// let style = report.preferred_context_formatting_style(handlers::FormattingFunction::Display);
1361    /// ```
1362    #[must_use]
1363    pub fn preferred_context_formatting_style(
1364        &self,
1365        report_formatting_function: FormattingFunction,
1366    ) -> ContextFormattingStyle {
1367        let report: ReportRef<'_, Dynamic, Uncloneable, Local> = self
1368            .as_uncloneable_ref()
1369            .into_dynamic()
1370            .into_uncloneable()
1371            .into_local();
1372        crate::hooks::context_formatter::get_preferred_context_formatting_style(
1373            report,
1374            report_formatting_function,
1375        )
1376    }
1377
1378    /// Gets the preferred formatting style for the context without hook
1379    /// processing.
1380    ///
1381    /// # Arguments
1382    ///
1383    /// - `report_formatting_function`: Whether the report in which this context
1384    ///   will be embedded is being formatted using [`Display`] formatting or
1385    ///   [`Debug`]
1386    ///
1387    /// [`Display`]: core::fmt::Display
1388    /// [`Debug`]: core::fmt::Debug
1389    ///
1390    /// # Examples
1391    /// ```
1392    /// # use rootcause::prelude::*;
1393    /// let report: Report = report!("error message");
1394    /// let style =
1395    ///     report.preferred_context_formatting_style_unhooked(handlers::FormattingFunction::Display);
1396    /// ```
1397    #[must_use]
1398    pub fn preferred_context_formatting_style_unhooked(
1399        &self,
1400        report_formatting_function: FormattingFunction,
1401    ) -> ContextFormattingStyle {
1402        self.as_uncloneable_ref()
1403            .preferred_context_formatting_style_unhooked(report_formatting_function)
1404    }
1405
1406    /// Returns the number of references to this report.
1407    ///
1408    /// # Examples
1409    /// ```
1410    /// # use rootcause::prelude::*;
1411    /// let report: Report = report!("error message");
1412    /// assert_eq!(report.strong_count(), 1); // We just created the report so it has a single owner
1413    /// ```
1414    #[must_use]
1415    pub fn strong_count(&self) -> usize {
1416        self.as_uncloneable_ref().strong_count()
1417    }
1418}
1419
1420impl<C: Sized, O, T> Report<C, O, T> {
1421    /// Returns a reference to the current context.
1422    ///
1423    /// # Examples
1424    /// ```
1425    /// # use rootcause::prelude::*;
1426    /// # struct MyError;
1427    /// # let my_error = MyError;
1428    /// let report: Report<MyError> = report!(my_error);
1429    /// let context: &MyError = report.current_context();
1430    /// ```
1431    #[must_use]
1432    pub fn current_context(&self) -> &C {
1433        self.as_uncloneable_ref().current_context()
1434    }
1435}
1436
1437impl<O, T> Report<Dynamic, O, T> {
1438    /// Attempts to downcast the current context to a specific type.
1439    ///
1440    /// Returns `Some(&C)` if the current context is of type `C`, otherwise
1441    /// returns `None`.
1442    ///
1443    /// # Examples
1444    /// ```
1445    /// # use rootcause::{prelude::*, markers::Dynamic};
1446    /// # struct MyError;
1447    /// let report: Report<MyError> = report!(MyError);
1448    /// let dyn_report: Report<Dynamic> = report.into_dynamic();
1449    /// let context: Option<&MyError> = dyn_report.downcast_current_context();
1450    /// assert!(context.is_some());
1451    /// ```
1452    #[must_use]
1453    pub fn downcast_current_context<C>(&self) -> Option<&C>
1454    where
1455        C: Sized + 'static,
1456    {
1457        self.as_uncloneable_ref().downcast_current_context()
1458    }
1459
1460    /// Downcasts the current context to a specific type without checking.
1461    ///
1462    /// # Safety
1463    ///
1464    /// The caller must ensure:
1465    ///
1466    /// 1. The current context is actually of type `C` (can be verified by
1467    ///    calling [`current_context_type_id()`] first)
1468    ///
1469    /// [`current_context_type_id()`]: Report::current_context_type_id
1470    ///
1471    /// # Examples
1472    /// ```
1473    /// # use rootcause::prelude::*;
1474    /// # use core::any::TypeId;
1475    /// # struct MyError;
1476    /// let report: Report<MyError> = report!(MyError);
1477    /// let dyn_report: Report = report.into_dynamic();
1478    ///
1479    /// // Verify the type first
1480    /// if dyn_report.current_context_type_id() == TypeId::of::<MyError>() {
1481    ///     // SAFETY: We verified the type matches
1482    ///     let context: &MyError = unsafe { dyn_report.downcast_current_context_unchecked() };
1483    /// }
1484    /// ```
1485    #[must_use]
1486    pub unsafe fn downcast_current_context_unchecked<C>(&self) -> &C
1487    where
1488        C: Sized + 'static,
1489    {
1490        let report = self.as_uncloneable_ref();
1491
1492        // SAFETY:
1493        // 1. Guaranteed by the caller
1494        unsafe { report.downcast_current_context_unchecked() }
1495    }
1496
1497    /// Attempts to downcast the report to a specific context type.
1498    ///
1499    /// Returns `Ok(report)` if the current context is of type `C`,
1500    /// otherwise returns `Err(self)` with the original report.
1501    ///
1502    /// # Examples
1503    /// ```
1504    /// # use rootcause::prelude::*;
1505    /// # struct MyError;
1506    /// let report: Report<MyError> = report!(MyError);
1507    /// let dyn_report: Report = report.into_dynamic();
1508    /// let downcasted: Result<Report<MyError>, _> = dyn_report.downcast_report();
1509    /// assert!(downcasted.is_ok());
1510    /// ```
1511    pub fn downcast_report<C>(self) -> Result<Report<C, O, T>, Self>
1512    where
1513        C: Sized + 'static,
1514    {
1515        if TypeId::of::<C>() == self.current_context_type_id() {
1516            // SAFETY:
1517            // 1. We just checked that the type IDs match.
1518            let report = unsafe { self.downcast_report_unchecked() };
1519
1520            Ok(report)
1521        } else {
1522            Err(self)
1523        }
1524    }
1525
1526    /// Downcasts the report to a specific context type without checking.
1527    ///
1528    /// # Safety
1529    ///
1530    /// The caller must ensure:
1531    ///
1532    /// 1. The current context is actually of type `C` (can be verified by
1533    ///    calling [`current_context_type_id()`] first)
1534    ///
1535    /// [`current_context_type_id()`]: Report::current_context_type_id
1536    ///
1537    /// # Examples
1538    /// ```
1539    /// # use rootcause::prelude::*;
1540    /// # use core::any::TypeId;
1541    /// # struct MyError;
1542    /// let report: Report<MyError> = report!(MyError);
1543    /// let dyn_report: Report = report.into_dynamic();
1544    ///
1545    /// // Verify the type first
1546    /// if dyn_report.current_context_type_id() == TypeId::of::<MyError>() {
1547    ///     // SAFETY: We verified the type matches
1548    ///     let downcasted: Report<MyError> = unsafe { dyn_report.downcast_report_unchecked() };
1549    /// }
1550    /// ```
1551    #[must_use]
1552    pub unsafe fn downcast_report_unchecked<C>(self) -> Report<C, O, T>
1553    where
1554        C: Sized + 'static,
1555    {
1556        let raw = self.into_raw();
1557
1558        // SAFETY:
1559        // 1. `C` is bounded by `Sized` in the function signature.
1560        // 2. This is guaranteed by the invariants of this type.
1561        // 3. This is guaranteed by the invariants of this type.
1562        // 4. Guaranteed by the caller
1563        // 5. This is guaranteed by the invariants of this type.
1564        // 6. This is guaranteed by the invariants of this type.
1565        // 7. This is guaranteed by the invariants of this type.
1566        // 8. This is guaranteed by the invariants of this type.
1567        unsafe { Report::from_raw(raw) }
1568    }
1569
1570    /// Returns an iterator over all contexts in the report hierarchy that can
1571    /// be downcast to the specified type `D`.
1572    ///
1573    /// Iterates over the complete report hierarchy (including this report)
1574    /// using [`iter_reports`](Self::iter_reports) and yields references to
1575    /// contexts that successfully downcast to `D`.
1576    ///
1577    /// This is a convenience method combining
1578    /// [`iter_reports`](Self::iter_reports) with
1579    /// [`downcast_current_context`](Report::downcast_current_context).
1580    ///
1581    /// See also: [`iter_reports`](Self::iter_reports) for iterating over all
1582    /// reports, [`downcast_current_context`](Report::downcast_current_context)
1583    /// for downcasting a single report's context.
1584    ///
1585    /// # Examples
1586    ///
1587    /// ```
1588    /// # use rootcause::prelude::*;
1589    /// # #[derive(Debug)]
1590    /// struct MyError {
1591    ///     code: u32,
1592    /// }
1593    /// # impl std::fmt::Display for MyError {
1594    /// #     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "error {}", self.code) }
1595    /// # }
1596    ///
1597    /// let child = report!(MyError { code: 404 }).into_dynamic();
1598    /// let mut root = report!(MyError { code: 500 }).into_dynamic();
1599    /// root.children_mut().push(child.into_cloneable());
1600    ///
1601    /// let codes: Vec<u32> = root
1602    ///     .iter_downcast_context::<MyError>()
1603    ///     .map(|e| e.code)
1604    ///     .collect();
1605    ///
1606    /// assert_eq!(codes, vec![500, 404]);
1607    /// ```
1608    pub fn iter_downcast_context<D>(&self) -> DowncastIterator<'_, D, O::RefMarker, T>
1609    where
1610        O: ReportOwnershipMarker,
1611        D: 'static,
1612    {
1613        DowncastIterator {
1614            iter: self.iter_reports(),
1615            _phantom: PhantomData,
1616        }
1617    }
1618}
1619
1620impl<C: Sized + Send + Sync> Report<C, Mutable, SendSync> {
1621    /// Creates a new [`Report`] with [`SendSync`] thread safety.
1622    ///
1623    /// This is a convenience method that calls [`Report::new`] with explicit
1624    /// [`SendSync`] thread safety. Use this method when you're having
1625    /// trouble with type inference for the thread safety parameter.
1626    ///
1627    /// The context will use the [`handlers::Error`] handler to format the
1628    /// context.
1629    ///
1630    /// # Examples
1631    /// ```
1632    /// # use rootcause::prelude::*;
1633    /// # #[derive(Debug)]
1634    /// # struct MyError;
1635    /// # impl core::error::Error for MyError {}
1636    /// # impl core::fmt::Display for MyError { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { unimplemented!() }}
1637    /// let report = Report::new_sendsync(MyError);
1638    /// ```
1639    #[track_caller]
1640    #[must_use]
1641    pub fn new_sendsync(context: C) -> Self
1642    where
1643        C: core::error::Error,
1644    {
1645        Self::new(context)
1646    }
1647
1648    /// Creates a new [`Report`] with [`SendSync`] thread safety and the given
1649    /// handler.
1650    ///
1651    /// This is a convenience method that calls [`Report::new_custom`] with
1652    /// explicit [`SendSync`] thread safety. Use this method when you're
1653    /// having trouble with type inference for the thread safety parameter.
1654    ///
1655    /// # Examples
1656    /// ```
1657    /// # use rootcause::prelude::*;
1658    /// let report = Report::new_sendsync_custom::<handlers::Display>("error");
1659    /// ```
1660    #[track_caller]
1661    #[must_use]
1662    pub fn new_sendsync_custom<H>(context: C) -> Self
1663    where
1664        H: ContextHandler<C>,
1665    {
1666        Self::new_custom::<H>(context)
1667    }
1668}
1669
1670impl<C: Sized> Report<C, Mutable, Local> {
1671    /// Creates a new [`Report`] with [`Local`] thread safety.
1672    ///
1673    /// This is a convenience method that calls [`Report::new`] with explicit
1674    /// [`Local`] thread safety. Use this method when you're having trouble
1675    /// with type inference for the thread safety parameter.
1676    ///
1677    /// The context will use the [`handlers::Error`] handler to format the
1678    /// context.
1679    ///
1680    /// # Examples
1681    /// ```
1682    /// # use rootcause::prelude::*;
1683    /// # #[derive(Debug)]
1684    /// # struct MyError;
1685    /// # impl core::error::Error for MyError {}
1686    /// # impl core::fmt::Display for MyError { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { unimplemented!() }}
1687    /// let report = Report::new_local(MyError);
1688    /// ```
1689    #[track_caller]
1690    #[must_use]
1691    pub fn new_local(context: C) -> Self
1692    where
1693        C: core::error::Error,
1694    {
1695        Self::new(context)
1696    }
1697
1698    /// Creates a new [`Report`] with [`Local`] thread safety and the given
1699    /// handler.
1700    ///
1701    /// This is a convenience method that calls [`Report::new_custom`] with
1702    /// explicit [`Local`] thread safety. Use this method when you're having
1703    /// trouble with type inference for the thread safety parameter.
1704    ///
1705    /// # Examples
1706    /// ```
1707    /// # use rootcause::prelude::*;
1708    /// let report = Report::new_local_custom::<handlers::Display>("error");
1709    /// ```
1710    #[track_caller]
1711    #[must_use]
1712    pub fn new_local_custom<H>(context: C) -> Self
1713    where
1714        H: ContextHandler<C>,
1715    {
1716        Self::new_custom::<H>(context)
1717    }
1718}
1719
1720// SAFETY: The `SendSync` marker indicates that all objects in the report are
1721// `Send`+`Sync`. Therefore it is safe to implement `Send`+`Sync` for the report
1722// itself.
1723unsafe impl<C: ?Sized, O> Send for Report<C, O, SendSync> {}
1724
1725// SAFETY: The `SendSync` marker indicates that all objects in the report are
1726// `Send`+`Sync`. Therefore it is safe to implement `Send`+`Sync` for the report
1727// itself.
1728unsafe impl<C: ?Sized, O> Sync for Report<C, O, SendSync> {}
1729
1730impl<C: Sized, T> From<C> for Report<C, Mutable, T>
1731where
1732    C: markers::ObjectMarkerFor<T> + core::error::Error,
1733{
1734    #[track_caller]
1735    fn from(context: C) -> Self {
1736        Report::new(context)
1737    }
1738}
1739
1740impl<C: Sized, T> From<C> for Report<C, Cloneable, T>
1741where
1742    C: markers::ObjectMarkerFor<T> + core::error::Error,
1743{
1744    #[track_caller]
1745    fn from(context: C) -> Self {
1746        Report::new(context).into_cloneable()
1747    }
1748}
1749
1750impl<C: Sized, T> From<C> for Report<Dynamic, Mutable, T>
1751where
1752    C: markers::ObjectMarkerFor<T> + core::error::Error,
1753{
1754    #[track_caller]
1755    fn from(context: C) -> Self {
1756        Report::new(context).into_dynamic()
1757    }
1758}
1759
1760impl<C: Sized, T> From<C> for Report<Dynamic, Cloneable, T>
1761where
1762    C: markers::ObjectMarkerFor<T> + core::error::Error,
1763{
1764    #[track_caller]
1765    fn from(context: C) -> Self {
1766        Report::new(context).into_dynamic().into_cloneable()
1767    }
1768}
1769
1770impl<C: ?Sized, T> Clone for Report<C, Cloneable, T> {
1771    fn clone(&self) -> Self {
1772        self.as_ref().clone_arc()
1773    }
1774}
1775
1776impl<C: ?Sized, O, T> core::fmt::Display for Report<C, O, T> {
1777    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1778        core::fmt::Display::fmt(&self.as_uncloneable_ref(), f)
1779    }
1780}
1781
1782impl<C: ?Sized, O, T> core::fmt::Debug for Report<C, O, T> {
1783    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1784        core::fmt::Debug::fmt(&self.as_uncloneable_ref(), f)
1785    }
1786}
1787
1788impl<C: ?Sized, O> core::ops::Deref for Report<C, O, SendSync> {
1789    type Target = dyn core::error::Error + Send + Sync + 'static;
1790
1791    fn deref(&self) -> &Self::Target {
1792        ErrorNoSourceWrapper::new(self)
1793    }
1794}
1795
1796impl<C: ?Sized, O> core::ops::Deref for Report<C, O, Local> {
1797    type Target = dyn core::error::Error + 'static;
1798
1799    fn deref(&self) -> &Self::Target {
1800        ErrorNoSourceWrapper::new(self)
1801    }
1802}
1803
1804impl<C: ?Sized, O> AsRef<dyn core::error::Error + Send + Sync> for Report<C, O, SendSync> {
1805    #[inline(always)]
1806    fn as_ref(&self) -> &(dyn core::error::Error + Send + Sync + 'static) {
1807        ErrorNoSourceWrapper::new(self)
1808    }
1809}
1810
1811impl<C: ?Sized, O> AsRef<dyn core::error::Error> for Report<C, O, Local> {
1812    #[inline(always)]
1813    fn as_ref(&self) -> &(dyn core::error::Error + 'static) {
1814        ErrorNoSourceWrapper::new(self)
1815    }
1816}
1817
1818impl<C: ?Sized, O, T> Unpin for Report<C, O, T> {}
1819
1820macro_rules! from_impls {
1821    ($(
1822        <
1823            $($param:ident),*
1824        >:
1825        $context1:ty => $context2:ty,
1826        $ownership1:ty => $ownership2:ty,
1827        $thread_safety1:ty => $thread_safety2:ty,
1828        [$($op:ident),*]
1829    ),* $(,)?) => {
1830        $(
1831            impl<$($param),*> From<Report<$context1, $ownership1, $thread_safety1>> for Report<$context2, $ownership2, $thread_safety2>
1832             {
1833                #[track_caller]
1834                fn from(report: Report<$context1, $ownership1, $thread_safety1>) -> Self {
1835                    report
1836                        $(.$op())*
1837                }
1838            }
1839        )*
1840    };
1841}
1842
1843from_impls!(
1844    <C>: C => C, Mutable => Mutable, SendSync => Local, [into_local],
1845    <C>: C => C, Mutable => Cloneable, SendSync => SendSync, [into_cloneable],
1846    <C>: C => C, Mutable => Cloneable, SendSync => Local, [into_cloneable, into_local],
1847    <C>: C => C, Mutable => Cloneable, Local => Local, [into_cloneable],
1848    <C>: C => C, Cloneable => Cloneable, SendSync => Local, [into_local],
1849    <C>: C => Dynamic, Mutable => Mutable, SendSync => SendSync, [into_dynamic],
1850    <C>: C => Dynamic, Mutable => Mutable, SendSync => Local, [into_dynamic, into_local],
1851    <C>: C => Dynamic, Mutable => Mutable, Local => Local, [into_dynamic],
1852    <C>: C => Dynamic, Mutable => Cloneable, SendSync => SendSync, [into_dynamic, into_cloneable],
1853    <C>: C => Dynamic, Mutable => Cloneable, SendSync => Local, [into_dynamic, into_cloneable, into_local],
1854    <C>: C => Dynamic, Mutable => Cloneable, Local => Local, [into_dynamic, into_cloneable],
1855    <C>: C => Dynamic, Cloneable => Cloneable, SendSync => SendSync, [into_dynamic, into_cloneable],
1856    <C>: C => Dynamic, Cloneable => Cloneable, SendSync => Local, [into_dynamic, into_cloneable, into_local],
1857    <C>: C => Dynamic, Cloneable => Cloneable, Local => Local, [into_dynamic, into_cloneable],
1858    <>:  Dynamic => Dynamic, Mutable => Mutable, SendSync => Local, [into_local],
1859    <>:  Dynamic => Dynamic, Mutable => Cloneable, SendSync => SendSync, [into_cloneable],
1860    <>:  Dynamic => Dynamic, Mutable => Cloneable, SendSync => Local, [into_cloneable, into_local],
1861    <>:  Dynamic => Dynamic, Mutable => Cloneable, Local => Local, [into_cloneable],
1862    <>:  Dynamic => Dynamic, Cloneable => Cloneable, SendSync => Local, [into_local],
1863);
1864
1865#[cfg(test)]
1866mod tests {
1867    use alloc::string::{String, ToString};
1868    use core::error::Error as StdError;
1869    use core::ops::Deref;
1870    use thiserror::Error;
1871
1872    use super::*;
1873
1874    #[allow(dead_code)]
1875    struct NonSend(*const ());
1876    static_assertions::assert_not_impl_any!(NonSend: Send, Sync);
1877
1878    #[test]
1879    fn test_report_send_sync() {
1880        static_assertions::assert_impl_all!(Report<(), Mutable, SendSync>: Send, Sync);
1881        static_assertions::assert_impl_all!(Report<(), Cloneable, SendSync>: Send, Sync);
1882        static_assertions::assert_impl_all!(Report<String, Mutable, SendSync>: Send, Sync);
1883        static_assertions::assert_impl_all!(Report<String, Cloneable, SendSync>: Send, Sync);
1884        static_assertions::assert_impl_all!(Report<NonSend, Mutable, SendSync>: Send, Sync); // This still makes sense, since you won't actually be able to construct this report
1885        static_assertions::assert_impl_all!(Report<NonSend, Cloneable, SendSync>: Send, Sync);
1886        static_assertions::assert_impl_all!(Report<Dynamic, Mutable, SendSync>: Send, Sync);
1887        static_assertions::assert_impl_all!(Report<Dynamic, Cloneable, SendSync>: Send, Sync);
1888
1889        static_assertions::assert_not_impl_any!(Report<(), Mutable, Local>: Send, Sync);
1890        static_assertions::assert_not_impl_any!(Report<(), Cloneable, Local>: Send, Sync);
1891        static_assertions::assert_not_impl_any!(Report<String, Mutable, Local>: Send, Sync);
1892        static_assertions::assert_not_impl_any!(Report<String, Cloneable, Local>: Send, Sync);
1893        static_assertions::assert_not_impl_any!(Report<NonSend, Mutable, Local>: Send, Sync);
1894        static_assertions::assert_not_impl_any!(Report<NonSend, Cloneable, Local>: Send, Sync);
1895        static_assertions::assert_not_impl_any!(Report<Dynamic, Mutable, Local>: Send, Sync);
1896        static_assertions::assert_not_impl_any!(Report<Dynamic, Cloneable, Local>: Send, Sync);
1897    }
1898
1899    #[test]
1900    fn test_report_unpin() {
1901        static_assertions::assert_impl_all!(Report<(), Mutable, SendSync>: Unpin);
1902        static_assertions::assert_impl_all!(Report<(), Cloneable, SendSync>: Unpin);
1903        static_assertions::assert_impl_all!(Report<String, Mutable, SendSync>: Unpin);
1904        static_assertions::assert_impl_all!(Report<String, Cloneable, SendSync>: Unpin);
1905        static_assertions::assert_impl_all!(Report<NonSend, Mutable, SendSync>: Unpin); // This still makes sense, since you won't actually be able to construct this report
1906        static_assertions::assert_impl_all!(Report<NonSend, Cloneable, SendSync>: Unpin);
1907        static_assertions::assert_impl_all!(Report<Dynamic, Mutable, SendSync>: Unpin);
1908        static_assertions::assert_impl_all!(Report<Dynamic, Cloneable, SendSync>: Unpin);
1909
1910        static_assertions::assert_impl_all!(Report<(), Mutable, Local>: Unpin);
1911        static_assertions::assert_impl_all!(Report<(), Cloneable, Local>: Unpin);
1912        static_assertions::assert_impl_all!(Report<String, Mutable, Local>: Unpin);
1913        static_assertions::assert_impl_all!(Report<String, Cloneable, Local>: Unpin);
1914        static_assertions::assert_impl_all!(Report<NonSend, Mutable, Local>: Unpin);
1915        static_assertions::assert_impl_all!(Report<NonSend, Cloneable, Local>: Unpin);
1916        static_assertions::assert_impl_all!(Report<Dynamic, Mutable, Local>: Unpin);
1917        static_assertions::assert_impl_all!(Report<Dynamic, Cloneable, Local>: Unpin);
1918    }
1919
1920    #[test]
1921    fn test_report_copy_clone() {
1922        static_assertions::assert_not_impl_any!(Report<(), Mutable, SendSync>: Copy, Clone);
1923        static_assertions::assert_not_impl_any!(Report<(), Mutable, Local>: Copy, Clone);
1924        static_assertions::assert_not_impl_any!(Report<String, Mutable, SendSync>: Copy, Clone);
1925        static_assertions::assert_not_impl_any!(Report<String, Mutable, Local>: Copy, Clone);
1926        static_assertions::assert_not_impl_any!(Report<NonSend, Mutable, SendSync>: Copy, Clone);
1927        static_assertions::assert_not_impl_any!(Report<NonSend, Mutable, Local>: Copy, Clone);
1928        static_assertions::assert_not_impl_any!(Report<Dynamic, Mutable, SendSync>: Copy, Clone);
1929        static_assertions::assert_not_impl_any!(Report<Dynamic, Mutable, Local>: Copy, Clone);
1930
1931        static_assertions::assert_impl_all!(Report<(), Cloneable, SendSync>: Clone);
1932        static_assertions::assert_impl_all!(Report<(), Cloneable, Local>: Clone);
1933        static_assertions::assert_impl_all!(Report<String, Cloneable, SendSync>: Clone);
1934        static_assertions::assert_impl_all!(Report<String, Cloneable, Local>: Clone);
1935        static_assertions::assert_impl_all!(Report<NonSend, Cloneable, SendSync>: Clone);
1936        static_assertions::assert_impl_all!(Report<NonSend, Cloneable, Local>: Clone);
1937        static_assertions::assert_impl_all!(Report<Dynamic, Cloneable, SendSync>: Clone);
1938        static_assertions::assert_impl_all!(Report<Dynamic, Cloneable, Local>: Clone);
1939
1940        static_assertions::assert_not_impl_any!(Report<(), Cloneable, SendSync>: Copy);
1941        static_assertions::assert_not_impl_any!(Report<(), Cloneable, Local>: Copy);
1942        static_assertions::assert_not_impl_any!(Report<String, Cloneable, SendSync>: Copy);
1943        static_assertions::assert_not_impl_any!(Report<String, Cloneable, Local>: Copy);
1944        static_assertions::assert_not_impl_any!(Report<NonSend, Cloneable, SendSync>: Copy);
1945        static_assertions::assert_not_impl_any!(Report<NonSend, Cloneable, Local>: Copy);
1946        static_assertions::assert_not_impl_any!(Report<Dynamic, Cloneable, SendSync>: Copy);
1947        static_assertions::assert_not_impl_any!(Report<Dynamic, Cloneable, Local>: Copy);
1948    }
1949
1950    #[derive(Debug, Error)]
1951    #[error("boom")]
1952    struct Boom;
1953
1954    #[derive(Debug, Error)]
1955    enum Outer {
1956        #[error(transparent)]
1957        Inner(#[from] Report<Boom>),
1958    }
1959
1960    fn make_report() -> Report<Boom> {
1961        Report::new(Boom)
1962    }
1963
1964    fn make_dynamic_report() -> Report<Dynamic> {
1965        make_report().into_dynamic()
1966    }
1967
1968    fn make_cloneable_report() -> Report<Boom, Cloneable> {
1969        make_report().into_cloneable()
1970    }
1971
1972    fn make_local_report() -> Report<Boom, Mutable, Local> {
1973        make_report().into_local()
1974    }
1975
1976    #[test]
1977    fn report_derefs_to_dyn_error() {
1978        let report = make_report();
1979
1980        let err: &(dyn StdError + Send + Sync) = report.deref();
1981
1982        assert!(err.to_string().contains("boom"));
1983    }
1984
1985    #[test]
1986    fn report_asrefs_to_dyn_error() {
1987        let report = make_report();
1988
1989        fn takes_asref(err: impl AsRef<dyn StdError + Send + Sync>) {
1990            assert!(err.as_ref().to_string().contains("boom"));
1991        }
1992
1993        takes_asref(&report);
1994    }
1995
1996    #[test]
1997    fn dynamic_report_derefs_to_dyn_error() {
1998        let report = make_dynamic_report();
1999
2000        let err: &dyn StdError = report.deref();
2001
2002        assert!(err.to_string().contains("boom"));
2003    }
2004
2005    #[test]
2006    fn dynamic_report_asrefs_to_dyn_error() {
2007        let report = make_dynamic_report();
2008
2009        fn takes_asref(err: impl AsRef<dyn StdError + Send + Sync>) {
2010            assert!(err.as_ref().to_string().contains("boom"));
2011        }
2012
2013        takes_asref(&report);
2014    }
2015
2016    #[test]
2017    fn cloneable_report_derefs_to_dyn_error() {
2018        let report = make_cloneable_report();
2019
2020        let err: &dyn StdError = report.deref();
2021
2022        assert!(err.to_string().contains("boom"));
2023    }
2024
2025    #[test]
2026    fn cloneable_report_asrefs_to_dyn_error() {
2027        let report = make_cloneable_report();
2028
2029        fn takes_asref(err: impl AsRef<dyn StdError + Send + Sync>) {
2030            assert!(err.as_ref().to_string().contains("boom"));
2031        }
2032
2033        takes_asref(&report);
2034    }
2035
2036    #[test]
2037    fn local_report_derefs_to_dyn_error() {
2038        let report = make_local_report();
2039
2040        let err: &dyn StdError = report.deref();
2041
2042        assert!(err.to_string().contains("boom"));
2043    }
2044
2045    #[test]
2046    fn local_report_asrefs_to_dyn_error() {
2047        let report = make_local_report();
2048
2049        fn takes_asref(err: impl AsRef<dyn StdError>) {
2050            assert!(err.as_ref().to_string().contains("boom"));
2051        }
2052
2053        takes_asref(&report);
2054    }
2055
2056    #[test]
2057    fn report_deref_supports_error_methods() {
2058        let report = make_report();
2059
2060        assert!(report.source().is_none());
2061    }
2062
2063    #[test]
2064    fn thiserror_from_works_for_report() {
2065        let report = make_report();
2066
2067        let outer: Outer = report.into();
2068
2069        match outer {
2070            Outer::Inner(inner) => {
2071                assert!(inner.to_string().contains("boom"));
2072            }
2073        }
2074    }
2075
2076    #[test]
2077    fn thiserror_question_mark_works_for_report() {
2078        fn inner() -> Result<(), Report<Boom>> {
2079            Err(make_report())
2080        }
2081
2082        fn outer() -> Result<(), Outer> {
2083            inner()?;
2084            Ok(())
2085        }
2086
2087        let err = outer().unwrap_err();
2088        assert!(err.to_string().contains("boom"));
2089    }
2090
2091    #[test]
2092    fn report_is_usable_where_dyn_error_is_expected() {
2093        fn takes_error(err: &dyn StdError) -> String {
2094            err.to_string()
2095        }
2096
2097        let report = make_report();
2098        assert!(takes_error(report.deref()).contains("boom"));
2099    }
2100}