//! Extended type erasure support. //! //! The `AnyTrait` trait provides dynamic upcasting to trait objects. mod erased; mod mut_any_unsized; mod ref_any_unsized; mod static_wrapper; pub mod type_name; mod type_name_id; use crate::hkt::Marker; pub use mut_any_unsized::*; pub use ref_any_unsized::*; pub use static_wrapper::*; pub use type_name_id::*; pub trait AnyTrait<'lt> { fn upcast_by_id(&self, id: WithLtTypeId<'lt>) -> Option> { let _id = id; None } fn upcast_by_id_mut(&mut self, id: WithLtTypeId<'lt>) -> Option> { let _id = id; None } } impl<'u, 'lt: 'u> dyn AnyTrait<'lt> + 'u { #[track_caller] pub fn upcast<'r, T: ?Sized + type_name::WithLt<'r, 'lt>>(&'r self) -> Option<&'r T> { self.upcast_by_id(WithLtTypeId::of::()) .map(|value| match value.downcast::() { Ok(value) => value, Err(_) => panic!("wrong type returned by upcast_by_id"), }) } #[track_caller] pub fn upcast_mut<'r, T: ?Sized + type_name::WithLt<'r, 'lt>>( &'r mut self, ) -> Option<&'r mut T> { self.upcast_by_id_mut(WithLtTypeId::of::()) .map(|value| match value.downcast::() { Ok(value) => value, Err(_) => panic!("wrong type returned by upcast_by_id_mut"), }) } } const _: () = { pub struct Ref(Marker); impl<'lt, 'ctx, T: ?Sized> type_name::Lower<'lt, 'ctx, &'lt &'ctx ()> for Ref where T: type_name::Lower<'lt, 'ctx, &'lt &'ctx ()>, { type Lowered = &'lt type_name::Lowered<'lt, 'ctx, T>; } impl<'lt, 'ctx, T: ?Sized> type_name::Raise<'lt, 'ctx, &'lt &'ctx ()> for &'lt T where T: type_name::Raise<'lt, 'ctx, &'lt &'ctx ()>, { type Raised = Ref>; } }; const _: () = { pub struct Mut(Marker); impl<'lt, 'ctx, T: ?Sized> type_name::Lower<'lt, 'ctx, &'lt &'ctx ()> for Mut where T: type_name::Lower<'lt, 'ctx, &'lt &'ctx ()>, { type Lowered = &'lt mut type_name::Lowered<'lt, 'ctx, T>; } impl<'lt, 'ctx, T: ?Sized> type_name::Raise<'lt, 'ctx, &'lt &'ctx ()> for &'lt mut T where T: type_name::Raise<'lt, 'ctx, &'lt &'ctx ()>, { type Raised = Mut>; } }; #[doc(hidden)] #[macro_export] macro_rules! trait_by_id { { & $this:ident, $id:ident, { type Impls = ($($trait:ty),* $(,)?); } } => {{ match $id { $( $id if $id == $crate::any::WithLtTypeId::of::<$trait>() => { return Some($crate::any::RefAnyUnsized::new($this as &$trait)) } )* _ => {} } }}; { &mut $this:ident, $id:ident, { type Impls = ($($trait:ty),* $(,)?); } } => {{ match $id { $( $id if $id == $crate::any::WithLtTypeId::of::<$trait>() => { return Some($crate::any::MutAnyUnsized::new($this as &mut $trait)) } )* _ => {} } }}; } #[doc(inline)] pub use trait_by_id;