konst_macro_rules/
type_eq.rs

1use core::marker::PhantomData;
2
3mod __ {
4    use super::*;
5
6    /// Value-level proof that `L` is the same type as `R`
7    ///
8    /// Type type can be used to prove that `L` and `R` are the same type,
9    /// because it can only be constructed with `TypeEq::<L, L>::NEW`,
10    /// where both type arguments are the same type.
11    pub struct TypeEq<L: ?Sized, R: ?Sized>(
12        PhantomData<(
13            fn(PhantomData<L>) -> PhantomData<L>,
14            fn(PhantomData<R>) -> PhantomData<R>,
15        )>,
16    );
17
18    impl<L: ?Sized> TypeEq<L, L> {
19        /// Constructs a `TypeEq<L, L>`.
20        pub const NEW: Self = TypeEq(PhantomData);
21    }
22}
23pub use __::TypeEq;
24
25impl<L: ?Sized, R: ?Sized> Copy for TypeEq<L, R> {}
26
27impl<L: ?Sized, R: ?Sized> Clone for TypeEq<L, R> {
28    fn clone(&self) -> Self {
29        *self
30    }
31}
32
33impl<L, R> TypeEq<L, R> {
34    /// Whether `L` is the same type as `R`.
35    const ARE_SAME_TYPE: Amb = {
36        // hacky way to emulate a lifetime-unaware
37        // `TypeId::of<L>() == TypeId::of<R>()`
38        let approx_same_type = {
39            core::mem::size_of::<L>() == core::mem::size_of::<R>()
40                && core::mem::align_of::<L>() == core::mem::align_of::<R>()
41                && core::mem::size_of::<Option<L>>() == core::mem::size_of::<Option<R>>()
42                && core::mem::align_of::<Option<L>>() == core::mem::align_of::<Option<R>>()
43        };
44
45        if approx_same_type {
46            Amb::Indefinite
47        } else {
48            Amb::No
49        }
50    };
51
52    /// Hints to the compiler that holding a `TypeEq<L, R>` where `L != R` is impossible.
53    #[inline(always)]
54    pub const fn reachability_hint(self) {
55        if let Amb::No = Self::ARE_SAME_TYPE {
56            // safety: it's impossible to have a `TypeEq<L, R>` value,
57            // where `L` and `R` are not the same type
58            #[cfg(feature = "rust_1_57")]
59            unsafe {
60                core::hint::unreachable_unchecked()
61            }
62            #[cfg(not(feature = "rust_1_57"))]
63            #[allow(unreachable_code)]
64            unsafe {
65                match crate::__priv_transmute!((), core::convert::Infallible, ()) {}
66            }
67        }
68    }
69
70    /// Transforms `L` to `R` given a `TypeEq<L, R>`
71    /// (the `TypeEq` value proves that `L` and `R` are the same type)
72    #[inline(always)]
73    pub const fn to_right(self, from: L) -> R {
74        self.reachability_hint();
75
76        unsafe { crate::__priv_transmute!(L, R, from) }
77    }
78}
79
80enum Amb {
81    // indefinitely false/true
82    Indefinite,
83    // definitely false
84    No,
85}