use core::any::TypeId; use crate::hkt::Invariant; use super::type_name; /// [`TypeId`] for lifetime containing types. /// /// This type supports a max of two lifetimes `'lt` and `'ctx`. /// Which are expected to be used like `dyn Trait<'ctx> + 'lt`. /// /// [`TypeId`] only allows `'static` types. /// This ID type splits the borrows out so that the borrow checker can check /// them independently. This does mean we must check the lifetimes at compile time. /// When `id_a == id_b` then the types are equal including the lifetimes. /// As such unsafe code can use this property to transmute values. #[derive(Copy, Clone)] pub struct WithLtTypeId<'lt> { /// We are invariant over 'lt so the borrow checker checks it for /// equality when doing `==`. _lt: Invariant<'lt>, /// Type ID of the higher ranked type. higher_type_id: TypeId, /// Name of the lifetime containing type for better error messages. #[cfg(feature = "better_errors")] name: &'static str, } impl<'lt> WithLtTypeId<'lt> { pub fn of<'u, T: ?Sized + type_name::WithLt<'u, 'lt>>() -> Self where 'lt: 'u, { Self { _lt: Invariant::NEW, // We get the TypeId of the 'static higher ranked type. higher_type_id: TypeId::of::>(), #[cfg(feature = "better_errors")] name: core::any::type_name::(), } } } impl<'lt> core::fmt::Debug for WithLtTypeId<'lt> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { #[cfg(feature = "better_errors")] { core::fmt::Display::fmt(self.name, f) } #[cfg(not(feature = "better_errors"))] { core::fmt::Debug::fmt(&self.higher_type_id, f) } } } impl<'lt> PartialEq for WithLtTypeId<'lt> { fn eq(&self, other: &Self) -> bool { self.higher_type_id == other.higher_type_id } } impl<'lt> Eq for WithLtTypeId<'lt> {} impl<'lt> PartialOrd for WithLtTypeId<'lt> { fn partial_cmp(&self, other: &Self) -> Option { Some(self.higher_type_id.cmp(&other.higher_type_id)) } } impl<'lt> Ord for WithLtTypeId<'lt> { fn cmp(&self, other: &Self) -> core::cmp::Ordering { self.higher_type_id.cmp(&other.higher_type_id) } } impl<'lt> core::hash::Hash for WithLtTypeId<'lt> { fn hash(&self, state: &mut H) { self.higher_type_id.hash(state); } }