Diffstat (limited to 'src/protocol.rs')
| -rw-r--r-- | src/protocol.rs | 103 |
1 files changed, 34 insertions, 69 deletions
diff --git a/src/protocol.rs b/src/protocol.rs index 8511c46..0c20eec 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -33,51 +33,14 @@ //! This is done via the help of the [`AnyImpl`] type. This is not required for the core //! idea of DIDETs. -/// Type nameable trait. -/// -/// Traits cannot by named in the type system. Trait objects can. However, -/// trait objects are not always `'static` so don't always have a -/// [`TypeId`][core::any::TypeId]. This trait provides a way to name a trait object -/// in the type system and with a `TypeId` even if it contains lifetimes. -/// -/// [`Protocol`] should be implemented on a marker type that is `'static`. -/// [`Protocol`] then gives a mapping from that marker type to a trait object -/// given by [`Protocol::Object`]. Its recommended to use uninhabited marker -/// types when possible as the marker never needs to exist as a value. -/// -/// The `'ctx` lifetime is a lifetime the trait object can contain. The `'a` lifetime -/// is the lifetime of a reference to the trait object. As such, the trait object -/// needs to live for at least `'a`. -/// -/// ``` -/// // Some trait we want to use as a protocol. -/// trait MyTrait<'ctx> {} -/// -/// // Type to name MyTrait in the type system. -/// enum MyTraitProtocol {} -/// -/// // By implementing this we map MyTraitProtocol to MyTrait. -/// impl Protocol for MyTraitProtocol { -/// type Object<'a, 'ctx: 'a> = dyn MyTrait<'ctx> + 'a; -/// } -/// ``` -pub trait Protocol<'ctx>: TypeNameable<'ctx> { - /// The trait object form of the trait. - /// - /// This should be of the form `dyn Trait<'ctx> + 'a` where `'a` sets the - /// required lifetime of the trait object. - /// - /// Note, it is possible (and safe) to put non-trait object type here, but - /// it is likely to not play well with [`AnyObject`]. - type Object<'a>: ?Sized where 'ctx: 'a; -} +use crate::any::{IndirectLtAny, LtAny, LtTypeId, Mut, Ref, TypeNameable}; pub trait Implementer<'ctx> { - fn interface(&self, id: LtTypeId<'ctx>) -> Option<&dyn LtAny<'ctx>>; + fn interface(&self, id: LtTypeId<'ctx>) -> Option<IndirectLtAny<'_, 'ctx, Ref>>; } pub trait ImplementerMut<'ctx> { - fn interface_mut(&mut self, id: LtTypeId<'ctx>) -> Option<&mut dyn LtAny<'ctx>>; + fn interface_mut<'a>(&'a mut self, id: LtTypeId<'ctx>) -> Option<IndirectLtAny<'a, 'ctx, Mut>> where 'ctx: 'a; } /// Extension trait for getting the implementation of a protocol. @@ -87,23 +50,23 @@ pub trait ImplementerMutExt<'ctx>: ImplementerMut<'ctx> { /// This wraps [`Implementer::interface`] and [`AnyImpl::downcast`]. /// If [`Implementer::interface`] returns a [`AnyImpl`] for the wrong protocol then a panic is /// generated. - fn interface_mut_for<'a, P: Protocol<'ctx>>(&'a mut self) -> Option<&'a mut P::Object<'a>> - where + fn interface_mut_for<'a, P: TypeNameable<'a, 'ctx>>(&'a mut self) -> Option<&'a mut P> + where 'ctx: 'a; } impl<'ctx, T: ImplementerMut<'ctx> + ?Sized> ImplementerMutExt<'ctx> for T { - fn interface_mut_for<'a, P: Protocol<'ctx>>(&'a mut self) -> Option<&'a mut P::Object<'a>> - where - 'ctx: 'a, + fn interface_mut_for<'a, P: TypeNameable<'a, 'ctx>>(&'a mut self) -> Option<&'a mut P> + where + 'ctx: 'a { match self.interface_mut(LtTypeId::of::<P>()) { - Some(interface) => match interface.downcast_mut::<P::Object<'a>>() { - Some(implementation) => Some(implementation), - None => panic!( + Some(interface) => match interface.downcast::<P>() { + Ok(implementation) => Some(implementation), + Err(interface) => panic!( "unexpected protocol implementation: `{:?}`, expected: `{:?}`", interface.id(), - P::id() + LtTypeId::of::<P>() ), }, None => None, @@ -116,17 +79,20 @@ impl<'ctx, T: ImplementerMut<'ctx> + ?Sized> ImplementerMutExt<'ctx> for T { #[macro_export] macro_rules! implementer { { - impl[$ctx:lifetime $($generic:tt)*] $name:ty = [$($protocol:ty),* $(,)?]; + impl[$a:lifetime, $ctx:lifetime $($generic:tt)*] $name:ty = [$($protocol:ty),* $(,)?]; } => { - impl<$ctx $($generic)*> $crate::protocol::Implementer<$ctx> for $name { + impl<$ctx $($generic)*> $crate::protocol::ImplementerMut<$ctx> for $name { #[inline] - fn interface( - &mut self, - id: $crate::protocol::ProtocolId - ) -> ::core::option::Option<$crate::protocol::AnyObject<'_, $ctx>> { + fn interface_mut<$a>( + &$a mut self, + id: $crate::any::LtTypeId<$ctx> + ) -> ::core::option::Option<$crate::any::IndirectLtAny<$a, $ctx, $crate::any::Mut>> + where + $ctx: $a + { match id { - $(id if id == $crate::protocol::ProtocolId::of::<$protocol>() - => Some($crate::protocol::AnyObject::new::<$protocol>(self)),)* + $(id if id == $crate::any::LtTypeId::of::<$protocol>() + => Some($crate::any::IndirectLtAny::<$a, $ctx, _>::new::<$protocol>(self as _)),)* _ => None } } @@ -136,30 +102,29 @@ macro_rules! implementer { #[doc(inline)] pub use implementer; -use crate::any::{LtTypeId, LtAny, TypeNameable}; - #[cfg(test)] mod test { + use crate::nameable; + use super::*; #[test] fn implementer_macro() { - struct X<T>(T); - - enum Y {} - trait Z {} - impl Protocol for Y { - type Object<'a, 'ctx> = dyn Z + 'a; + nameable! { + ['a, 'ctx] + dyn Z + 'a where {'ctx: 'a} } + struct X<T>(T); + + impl<T: Clone> Z for X<T> {} + implementer! { - impl['ctx, T: Clone] X<T> = [ - Y + impl['a, 'ctx, T: Clone] X<T> = [ + dyn Z + 'a ]; } - - impl<T: Clone> Z for X<T> {} } } |