1use core::marker::PhantomData;
23mod __ {
4use super::*;
56/// 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.
11pub struct TypeEq<L: ?Sized, R: ?Sized>(
12 PhantomData<(
13fn(PhantomData<L>) -> PhantomData<L>,
14fn(PhantomData<R>) -> PhantomData<R>,
15 )>,
16 );
1718impl<L: ?Sized> TypeEq<L, L> {
19/// Constructs a `TypeEq<L, L>`.
20pub const NEW: Self = TypeEq(PhantomData);
21 }
22}
23pub use __::TypeEq;
2425impl<L: ?Sized, R: ?Sized> Copy for TypeEq<L, R> {}
2627impl<L: ?Sized, R: ?Sized> Clone for TypeEq<L, R> {
28fn clone(&self) -> Self {
29*self
30}
31}
3233impl<L, R> TypeEq<L, R> {
34/// Whether `L` is the same type as `R`.
35const ARE_SAME_TYPE: Amb = {
36// hacky way to emulate a lifetime-unaware
37 // `TypeId::of<L>() == TypeId::of<R>()`
38let 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 };
4445if approx_same_type {
46 Amb::Indefinite
47 } else {
48 Amb::No
49 }
50 };
5152/// Hints to the compiler that holding a `TypeEq<L, R>` where `L != R` is impossible.
53#[inline(always)]
54pub const fn reachability_hint(self) {
55if 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")]
59unsafe {
60 core::hint::unreachable_unchecked()
61 }
62#[cfg(not(feature = "rust_1_57"))]
63 #[allow(unreachable_code)]
64unsafe {
65match crate::__priv_transmute!((), core::convert::Infallible, ()) {}
66 }
67 }
68 }
6970/// 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)]
73pub const fn to_right(self, from: L) -> R {
74self.reachability_hint();
7576unsafe { crate::__priv_transmute!(L, R, from) }
77 }
78}
7980enum Amb {
81// indefinitely false/true
82Indefinite,
83// definitely false
84No,
85}