1 | // Contains the machinery necessary to print useful `assert!` messages. Not intended for public |
2 | // usage, not even nightly use-cases. |
3 | // |
4 | // Based on https://github.com/dtolnay/case-studies/tree/master/autoref-specialization. When |
5 | // 'specialization' is robust enough (5 years? 10 years? Never?), `Capture` can be specialized |
6 | // to [Printable]. |
7 | |
8 | #![allow (missing_debug_implementations)] |
9 | #![doc (hidden)] |
10 | #![unstable (feature = "generic_assert_internals" , issue = "44838" )] |
11 | |
12 | use crate::fmt::{Debug, Formatter}; |
13 | use crate::marker::PhantomData; |
14 | |
15 | // ***** TryCapture - Generic ***** |
16 | |
17 | /// Marker used by [Capture] |
18 | #[unstable (feature = "generic_assert_internals" , issue = "44838" )] |
19 | pub struct TryCaptureWithoutDebug; |
20 | |
21 | /// Catches an arbitrary `E` and modifies `to` accordingly |
22 | #[unstable (feature = "generic_assert_internals" , issue = "44838" )] |
23 | pub trait TryCaptureGeneric<E, M> { |
24 | /// Similar to [TryCapturePrintable] but generic to any `E`. |
25 | fn try_capture(&self, to: &mut Capture<E, M>); |
26 | } |
27 | |
28 | impl<E> TryCaptureGeneric<E, TryCaptureWithoutDebug> for &Wrapper<&E> { |
29 | #[inline ] |
30 | fn try_capture(&self, _: &mut Capture<E, TryCaptureWithoutDebug>) {} |
31 | } |
32 | |
33 | impl<E> Debug for Capture<E, TryCaptureWithoutDebug> { |
34 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> { |
35 | f.write_str(data:"N/A" ) |
36 | } |
37 | } |
38 | |
39 | // ***** TryCapture - Printable ***** |
40 | |
41 | /// Marker used by [Capture] |
42 | #[unstable (feature = "generic_assert_internals" , issue = "44838" )] |
43 | pub struct TryCaptureWithDebug; |
44 | |
45 | /// Catches an arbitrary `E: Printable` and modifies `to` accordingly |
46 | #[unstable (feature = "generic_assert_internals" , issue = "44838" )] |
47 | pub trait TryCapturePrintable<E, M> { |
48 | /// Similar as [TryCaptureGeneric] but specialized to any `E: Printable`. |
49 | fn try_capture(&self, to: &mut Capture<E, M>); |
50 | } |
51 | |
52 | impl<E> TryCapturePrintable<E, TryCaptureWithDebug> for Wrapper<&E> |
53 | where |
54 | E: Printable, |
55 | { |
56 | #[inline ] |
57 | fn try_capture(&self, to: &mut Capture<E, TryCaptureWithDebug>) { |
58 | to.elem = Some(*self.0); |
59 | } |
60 | } |
61 | |
62 | impl<E> Debug for Capture<E, TryCaptureWithDebug> |
63 | where |
64 | E: Printable, |
65 | { |
66 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> { |
67 | match self.elem { |
68 | None => f.write_str(data:"N/A" ), |
69 | Some(ref value: &E) => Debug::fmt(self:value, f), |
70 | } |
71 | } |
72 | } |
73 | |
74 | // ***** Others ***** |
75 | |
76 | /// All possible captured `assert!` elements |
77 | /// |
78 | /// # Types |
79 | /// |
80 | /// * `E`: **E**lement that is going to be displayed. |
81 | /// * `M`: **M**arker used to differentiate [Capture]s in regards to [Debug]. |
82 | #[unstable (feature = "generic_assert_internals" , issue = "44838" )] |
83 | pub struct Capture<E, M> { |
84 | // If None, then `E` does not implements [Printable] or `E` wasn't evaluated (`assert!( ... )` |
85 | // short-circuited). |
86 | // |
87 | // If Some, then `E` implements [Printable] and was evaluated. |
88 | pub elem: Option<E>, |
89 | phantom: PhantomData<M>, |
90 | } |
91 | |
92 | impl<M, T> Capture<M, T> { |
93 | #[inline ] |
94 | pub const fn new() -> Self { |
95 | Self { elem: None, phantom: PhantomData } |
96 | } |
97 | } |
98 | |
99 | /// Necessary for the implementations of `TryCapture*` |
100 | #[unstable (feature = "generic_assert_internals" , issue = "44838" )] |
101 | pub struct Wrapper<T>(pub T); |
102 | |
103 | /// Tells which elements can be copied and displayed |
104 | #[unstable (feature = "generic_assert_internals" , issue = "44838" )] |
105 | pub trait Printable: Copy + Debug {} |
106 | |
107 | impl<T> Printable for T where T: Copy + Debug {} |
108 | |