new lifetime containing type ids are working
Konnor Andrews 2024-02-04
parent f8d6526 · commit d177813
-rw-r--r--src/any.rs290
-rw-r--r--src/builtins.rs2
-rw-r--r--src/builtins/walker/hint.rs101
-rw-r--r--src/lib.rs8
-rw-r--r--src/protocol.rs103
5 files changed, 353 insertions, 151 deletions
diff --git a/src/any.rs b/src/any.rs
index 60c6b80..36905f6 100644
--- a/src/any.rs
+++ b/src/any.rs
@@ -1,19 +1,85 @@
-//! Heapless type erasure.
-//!
-//! [`Any`] is generic over the type of indirection (`&T`, `&mut T`, `Box<T>`)
-//! and allows erasing the `T` of the indirection. This is similar to replacing the `T` with
-//! [`core::any::Any`]. The main difference to [`core::any::Any`] is
+use core::{
+ marker::{PhantomData, PhantomPinned},
+ mem::{ManuallyDrop, MaybeUninit},
+};
-use core::marker::PhantomData;
+pub trait TypeNameable<'a, 'lt>: 'a {
+ type Name: ?Sized + TypeName<'a, 'lt, Nameable = Self>;
+}
+
+pub trait TypeName<'a, 'lt>: 'static {
+ type Nameable: ?Sized + TypeNameable<'a, 'lt, Name = Self>;
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! nameable {
+ {
+ $vis:vis [$a:lifetime, $lt:lifetime $(, $($generic:ident)*)?]
+
+ $type:ty
+ where {$($bound:tt)*}
+ } => {
+ $crate::any::nameable! {
+ $vis [$a, $lt $(, $($generic)*)?]
+
+ $type
+ where {$($bound)*}
-pub trait TypeNameable<'lt> {
- type Name: TypeName<'lt, Nameable = Self>;
+ $type
+ where {$($bound)*}
+ }
+ };
+ {
+ $vis:vis [$a:lifetime, $lt:lifetime $(, $($generic:ident)*)?]
+
+ $type:ty
+ where {$($bound:tt)*}
+
+ $type2:ty
+ where {$($bound2:tt)*}
+ } => {
+ const _: () = {
+ impl<$a, $lt $(, $($generic: $crate::any::TypeNameable<$a, $lt>)*)?>
+ $crate::any::TypeNameable<$a, $lt> for $type
+ where
+ $($bound)*
+ {
+ type Name = Name$(<$($generic::Name),*>)?;
+ }
+
+ $vis struct Name$(< $($generic: ?Sized),* >)?(
+ ::core::marker::PhantomData<fn() -> ($( $(*const $generic,)* )?)>
+ );
+
+ impl<$a, $lt $(, $($generic: $crate::any::TypeName<$a, $lt>)*)?>
+ $crate::any::TypeName<$a, $lt> for Name$(<$($generic),*>)?
+ where
+ $($bound2)*
+ {
+ type Nameable = $type2;
+ }
+ };
+ };
}
+#[doc(inline)]
+pub use nameable;
-pub trait TypeName<'lt>: 'static {
- type Nameable: ?Sized + TypeNameable<'lt, Name = Self>;
+pub struct Owned<T: ?Sized>(pub T);
+nameable! {
+ pub ['a, 'lt, T]
+ Owned<T> where {T: ?Sized}
+ Owned<T::Nameable> where {T: ?Sized}
}
+// pub struct Borrowed<'lt, T: ?Sized>(pub &'lt T);
+// nameable!(['a, 'lt: 'a, T: ?Sized + 'static]: Borrowed<'lt, T> => Borrowed<'static, T>);
+//
+// pub struct MutBorrowed<'lt, T: ?Sized>(pub &'lt mut T);
+// nameable!(['a, 'lt: 'a, T: ?Sized + 'static]: MutBorrowed<'lt, T> => MutBorrowed<'static, T>);
+
+// box here
+
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Clone, Debug)]
pub struct LtTypeId<'lt> {
_marker: PhantomData<fn(&'lt ()) -> &'lt ()>,
@@ -21,7 +87,7 @@ pub struct LtTypeId<'lt> {
}
impl<'lt> LtTypeId<'lt> {
- pub fn of<T: ?Sized + TypeNameable<'lt>>() -> Self {
+ pub fn of<'a, T: ?Sized + TypeNameable<'a, 'lt>>() -> Self {
LtTypeId {
_marker: PhantomData,
name_id: core::any::TypeId::of::<T::Name>(),
@@ -33,18 +99,18 @@ pub unsafe trait LtAny<'lt> {
fn type_id(&self) -> LtTypeId<'lt>;
}
-unsafe impl<'lt, T: ?Sized + TypeNameable<'lt>> LtAny<'lt> for T {
+unsafe impl<'a, 'lt, T: ?Sized + TypeNameable<'a, 'lt>> LtAny<'lt> for T {
fn type_id(&self) -> LtTypeId<'lt> {
LtTypeId::of::<T>()
}
}
impl<'a, 'lt> dyn LtAny<'lt> + 'a {
- pub fn is<T: ?Sized + TypeNameable<'lt>>(&self) -> bool {
+ pub fn is<T: ?Sized + TypeNameable<'a, 'lt>>(&self) -> bool {
LtTypeId::of::<T>() == self.type_id()
}
-
- pub fn downcast_ref<T: ?Sized + TypeNameable<'lt>>(&self) -> Option<&T> {
+
+ pub fn downcast_ref<T: TypeNameable<'a, 'lt>>(&self) -> Option<&T> {
if self.is::<T>() {
Some(unsafe { &*(self as *const dyn LtAny<'lt> as *const T) })
} else {
@@ -52,7 +118,7 @@ impl<'a, 'lt> dyn LtAny<'lt> + 'a {
}
}
- pub fn downcast_mut<T: ?Sized + TypeNameable<'lt>>(&mut self) -> Option<&mut T> {
+ pub fn downcast_mut<T: TypeNameable<'a, 'lt>>(&mut self) -> Option<&mut T> {
if self.is::<T>() {
Some(unsafe { &mut *(self as *mut dyn LtAny<'lt> as *mut T) })
} else {
@@ -61,7 +127,7 @@ impl<'a, 'lt> dyn LtAny<'lt> + 'a {
}
#[cfg(feature = "alloc")]
- pub fn downcast_box<T: TypeNameable<'lt>>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
+ pub fn downcast_box<T: TypeNameable<'a, 'lt>>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
if self.is::<T>() {
Ok(unsafe {
let raw: *mut dyn LtAny<'lt> = Box::into_raw(self);
@@ -73,73 +139,177 @@ impl<'a, 'lt> dyn LtAny<'lt> + 'a {
}
}
-#[doc(hidden)]
-#[macro_export]
-macro_rules! nameable {
- {$lt:lifetime: $type:ty => $name:ty} => {
- impl<$lt> $crate::any::TypeNameable<$lt> for $type {
- type Name = $name;
+#[must_use]
+pub struct IndirectLtAny<'a, 'lt: 'a, I: Indirect<'a>> {
+ info: fn() -> (LtTypeId<'lt>, unsafe fn(RawIndirect)),
+ indirect: RawIndirect,
+ _marker: PhantomData<(I::ForT<fn(&'lt ()) -> &'lt ()>, PhantomPinned)>,
+}
+
+impl<'a, 'lt, I: Indirect<'a>> Drop for IndirectLtAny<'a, 'lt, I> {
+ fn drop(&mut self) {
+ // We need to drop the stored value.
+
+ // Lookup drop function.
+ let (_, drop_fn) = (self.info)();
+
+ // SAFETY: self.indirect is never touched again.
+ // Additionally, we know that drop_fn is for this self.indirect because it was
+ // made by Self::new.
+ unsafe { drop_fn(self.indirect) };
+ }
+}
+
+impl<'a, 'lt, I: Indirect<'a>> IndirectLtAny<'a, 'lt, I> {
+ /// Wrap an indirection.
+ ///
+ /// The inner type `T` of the indirection is erased.
+ pub fn new<T: ?Sized + TypeNameable<'a, 'lt>>(indirect: I::ForT<T>) -> Self {
+ Self {
+ info: || {
+ (LtTypeId::of::<T>(), |raw| {
+ // SAFETY: This is only called in the drop impl.
+ unsafe { drop(I::from_raw::<T>(raw)) }
+ })
+ },
+ indirect: I::into_raw(indirect),
+ _marker: PhantomData,
}
+ }
+
+ /// Downcast to an indirection with a given `T` type.
+ ///
+ /// If the type of the stored value is different, then `self` is
+ /// returned as is.
+ pub fn downcast<T: ?Sized + TypeNameable<'a, 'lt>>(self) -> Result<I::ForT<T>, Self> {
+ let (id, _) = (self.info)();
- impl<$lt> TypeName<$lt> for $name {
- type Nameable = $type;
+ if id == LtTypeId::of::<T>() {
+ Ok(unsafe { I::from_raw::<T>(self.indirect) })
+ } else {
+ Err(self)
}
}
+
+ /// Type ID of the stored value's `T`.
+ pub fn id(&self) -> LtTypeId<'lt> {
+ (self.info)().0
+ }
}
-#[doc(inline)]
-pub use nameable;
-#[cfg(test)]
-mod test {
- use super::*;
+pub unsafe trait Indirect<'a> {
+ type ForT<T: ?Sized + 'a>: 'a;
- #[derive(Debug, PartialEq)]
- struct X<'a>(&'a mut i32);
+ fn into_raw<T: ?Sized + 'a>(value: Self::ForT<T>) -> RawIndirect;
+
+ unsafe fn from_raw<T: ?Sized + 'a>(any: RawIndirect) -> Self::ForT<T>;
+}
- nameable!('a: X<'a> => X<'static>);
+#[derive(Clone, Copy)]
+#[repr(transparent)]
+pub struct RawIndirect(MaybeUninit<[u8; INDIRECT_SIZE]>);
- #[test]
- fn any() {
- let mut x = 42;
- let x = X(&mut x);
+const INDIRECT_SIZE: usize = core::mem::size_of::<usize>() * 2;
- let any: &dyn LtAny = &x;
+trait Helper {}
- let y = any.downcast_ref().unwrap();
+pub enum Ref {}
- assert_eq!(x, *y);
+const _: () = assert!(core::mem::size_of::<&dyn Helper>() <= core::mem::size_of::<RawIndirect>());
+
+unsafe impl<'a> Indirect<'a> for Ref {
+ type ForT<T: ?Sized + 'a> = &'a T;
+
+ fn into_raw<T: ?Sized + 'a>(value: Self::ForT<T>) -> RawIndirect {
+ unsafe { transmute::<&'a T, RawIndirect>(value) }
}
- #[test]
- #[cfg(feature = "alloc")]
- fn any_box() {
- let mut x = 42;
- let x = X(&mut x);
+ unsafe fn from_raw<T: ?Sized + 'a>(any: RawIndirect) -> Self::ForT<T> {
+ unsafe { transmute::<RawIndirect, &'a T>(any) }
+ }
+}
- let any: Box<dyn LtAny> = Box::new(x);
+pub enum Mut {}
- let Ok(y) = any.downcast_box::<X>() else { panic!() };
+const _: () =
+ assert!(core::mem::size_of::<&mut dyn Helper>() <= core::mem::size_of::<RawIndirect>());
- assert_eq!(*y.0, 42);
+unsafe impl<'a> Indirect<'a> for Mut {
+ type ForT<T: ?Sized + 'a> = &'a mut T;
+
+ fn into_raw<T: ?Sized + 'a>(value: Self::ForT<T>) -> RawIndirect {
+ unsafe { transmute::<&'a mut T, RawIndirect>(value) }
+ }
+
+ unsafe fn from_raw<T: ?Sized + 'a>(any: RawIndirect) -> Self::ForT<T> {
+ unsafe { transmute::<RawIndirect, &'a mut T>(any) }
}
+}
- #[test]
- fn equal() {
- let mut x = 42;
- let x = X(&mut x);
+#[cfg(feature = "alloc")]
+pub use boxed::*;
+#[cfg(feature = "alloc")]
+mod boxed {
+ use super::*;
+
+ #[cfg(not(feature = "std"))]
+ use alloc::boxed::Box;
- let any: &dyn LtAny = &x;
+ /// A `Box<T>` indirection.
+ pub enum Boxed {}
- {
- let mut x2 = 42;
- let x2 = X(&mut x2);
+ const _: () =
+ assert!(core::mem::size_of::<Box<dyn Helper>>() <= core::mem::size_of::<RawIndirect>());
- let any2: &dyn LtAny = &x2;
+ unsafe impl<'a> Indirect<'a> for Boxed {
+ type ForT<T: ?Sized + 'a> = Box<T>;
- assert_eq!(any.type_id(), any2.type_id());
+ fn into_raw<T: ?Sized + 'a>(value: Box<T>) -> RawIndirect {
+ unsafe { transmute::<Box<T>, RawIndirect>(value) }
}
- // Forcing any to live until here will make it fail.
- // drop(any);
+ unsafe fn from_raw<T: ?Sized + 'a>(any: RawIndirect) -> Box<T> {
+ unsafe { transmute::<RawIndirect, Box<T>>(any) }
+ }
+ }
+}
+
+/// # Safety
+/// Same rules as [`core::mem::transmute()`].
+unsafe fn transmute<T, U>(value: T) -> U {
+ // Create union type that can store a `T` or a `U`.
+ // We can then use this to convert between them.
+ //
+ // The repr(C) layout forces no offset between `t` and `u` as talked about here
+ // https://rust-lang.github.io/unsafe-code-guidelines/layout/unions.html#c-compatible-layout-repr-c
+ #[repr(C)]
+ union Transmute<T, U> {
+ t: ManuallyDrop<T>,
+ u: ManuallyDrop<U>,
+ }
+
+ // Create the union in the `T` state.
+ let value = Transmute {
+ t: ManuallyDrop::new(value),
+ };
+
+ // Read from the union in the `U` state.
+ // SAFETY: This is safe because the caller has promised that `T` can be transmuted to `U`.
+ // The following reference link talks about repr(C) unions being used this way.
+ // https://doc.rust-lang.org/reference/items/unions.html#reading-and-writing-union-fields
+ ManuallyDrop::into_inner(unsafe { value.u })
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[derive(Debug, PartialEq)]
+ struct X<'a>(&'a mut i32);
+
+ nameable! {
+ ['a, 'lt]
+ X<'lt> where {'lt: 'a}
+ X<'lt> where {'lt: 'a}
}
}
diff --git a/src/builtins.rs b/src/builtins.rs
index 3a5e50e..823135f 100644
--- a/src/builtins.rs
+++ b/src/builtins.rs
@@ -1,2 +1,2 @@
-pub mod visitor;
+// pub mod visitor;
pub mod walker;
diff --git a/src/builtins/walker/hint.rs b/src/builtins/walker/hint.rs
index 42234e9..4392f73 100644
--- a/src/builtins/walker/hint.rs
+++ b/src/builtins/walker/hint.rs
@@ -4,42 +4,109 @@
//! this module gives a protocol by which a visitor can give a hint
//! to the walker about what it is expecting.
-use crate::protocol::{Implementer, Protocol};
+use core::marker::PhantomData;
-/// Protocol for giving a hint to a walker.
-///
-/// A hint is for a particular protocol `P`.
-pub struct Hint<P: Meta>(P);
+use crate::{
+ any::{TypeName, TypeNameable},
+ nameable,
+ protocol::Implementer,
+};
/// Meta information for the hint.
///
/// This gives the visitor more information to work from when selecting a hint.
-pub trait Meta: Protocol {
+pub trait Meta<'ctx> {
/// Information known by the walker.
///
/// This should be information easy to get without changing the state of the walker
/// in an irreversable way.
- type Known<'a, 'ctx: 'a>;
+ type Known<'a>;
/// Extra information the visitor can give to the walker about what it is expecting.
- type Hint<'a, 'ctx: 'a>;
+ type Hint<'a>;
}
/// Object implementing the [`Hint`] protocol.
-pub trait Object<'ctx, P: Meta> {
+pub trait Hint<'ctx, P: Meta<'ctx>> {
/// Hint to the walker to use the `P` protocol.
///
/// This should only be called once per [`RequestHint`].
- fn hint(
- &mut self,
- visitor: &mut dyn Implementer<'ctx>,
- hint: P::Hint<'_, 'ctx>,
- ) -> Result<(), ()>;
+ fn hint(&mut self, visitor: &mut dyn Implementer<'ctx>, hint: P::Hint<'_>) -> Result<(), ()>;
/// Ask the walker for information about it's support of the protocol.
- fn known(&mut self, hint: &P::Hint<'_, 'ctx>) -> Result<P::Known<'_, 'ctx>, ()>;
+ fn known(&mut self, hint: &P::Hint<'_>) -> Result<P::Known<'_>, ()>;
}
-impl<P: Meta> Protocol for Hint<P> {
- type Object<'a, 'ctx: 'a> = &'a mut dyn Object<'ctx, P>;
+// nameable!(['a, 'ctx, P: Meta<'ctx> + TypeNameable<'a, 'ctx>]: dyn Hint<'ctx, P> + 'a => dyn Hint<'static, P::Name>);
+
+const _: () = {
+ impl<'a, 'ctx: 'a, P: TypeNameable<'a, 'ctx>>
+ crate::any::TypeNameable<'a, 'ctx> for dyn Hint<'ctx, P> + 'a
+ where
+ P: ?Sized
+ // where
+ // P: Meta<'ctx>
+ {
+ type Name = Name<P::Name>;
+ }
+
+ pub struct Name<T: ?Sized>(PhantomData<fn() -> *const T>);
+
+ impl<'a, 'ctx: 'a, T: TypeName<'a, 'ctx>> crate::any::TypeName<'a, 'ctx> for Name<T>
+ where
+ T: ?Sized
+ // where
+ // T::Nameable: Meta<'ctx>,
+ {
+ type Nameable = dyn Hint<'ctx, T::Nameable> + 'a;
+ }
+};
+
+#[cfg(test)]
+mod test {
+ use crate::any::LtTypeId;
+
+ use super::*;
+
+ #[test]
+ fn demo() {
+ struct X;
+ struct Y;
+
+ nameable!(['a, 'ctx]: Y => Y);
+
+ impl<'ctx, X> Hint<'ctx, Y> for X {
+ fn hint(
+ &mut self,
+ visitor: &mut dyn Implementer<'ctx>,
+ hint: <Y as Meta>::Hint<'_>,
+ ) -> Result<(), ()> {
+ todo!()
+ }
+
+ fn known(
+ &mut self,
+ hint: &<Y as Meta>::Hint<'_>,
+ ) -> Result<<Y as Meta>::Known<'_>, ()> {
+ todo!()
+ }
+ }
+
+ impl<'ctx> Meta<'ctx> for Y {
+ type Known<'a> = ();
+
+ type Hint<'a> = ();
+ }
+
+ let x = X;
+ let y: &dyn Hint<Y> = &x;
+
+ fn id<'a, 'ctx, T: ?Sized + TypeNameable<'a, 'ctx>>(x: &T) {
+ dbg!(LtTypeId::of::<T>());
+ }
+
+ id(y);
+
+ todo!();
+ }
}
diff --git a/src/lib.rs b/src/lib.rs
index ba3a695..02c8f9e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -6,12 +6,12 @@
#[cfg(feature = "alloc")]
extern crate alloc;
-// mod build;
-// pub mod builtins;
-// pub mod protocol;
pub mod any;
+mod build;
+// pub mod builtins;
+pub mod protocol;
pub mod symbol;
-// mod walk;
+mod walk;
// pub mod impls;
// pub mod transform;
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> {}
}
}