Skip to main content

rootcause/report/
owned.rs

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