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