Diffstat (limited to 'src/any.rs')
| -rw-r--r-- | src/any.rs | 214 |
1 files changed, 89 insertions, 125 deletions
@@ -6,7 +6,7 @@ pub mod indirect; mod static_wrapper; mod type_name_id; -use crate::{bijective_higher_ranked_trait, bijective_higher_ranked_type, hkt::Invariant}; +use crate::{higher_ranked_trait, higher_ranked_type, hkt::{Invariant, Marker}}; use core::marker::PhantomData; pub use static_wrapper::*; @@ -15,100 +15,70 @@ pub use type_name_id::*; #[cfg(all(feature = "alloc", not(feature = "std")))] use alloc::boxed::Box; -bijective_higher_ranked_trait! { - /// Higher ranked types with a context `'ctx` lifetime. - /// - /// Its recommended to name types of this class with a `Dyn` prefix. - /// This prefix was chosen because most lower types used in treaty are trait objects. - /// - /// This is most important for trait objects. For example `dyn MyTrait<'ctx> + 'a` this - /// type has a "extra" `'a` lifetime for how long its valid for. This higher ranked type class - /// allows naming the trait object type without a `'a` being given. - pub type class WithContextLt['ctx][]: {} [for<'a>] -} +higher_ranked_trait! { + pub type class TypeName for<'a, 'ctx> { + type Bound = &'a &'ctx (); -bijective_higher_ranked_trait! { - /// Higher ranked types that are `'static`. - /// - /// Types of this class can usually be sealed as they don't need to be named directly. - /// - /// Higher ranked types of this form have a [`TypeId`][core::any::TypeId] associated with them. - /// This allows them to be used as a name for lifetime containing types. - /// - /// This type class has members in the [`WithContextLt`] higher ranked type class. - /// To get a concrete type two lowerings need to be applied to inject two lifetimes. - /// One for the context lifetime, and one for the lifetime of the concrete type. - pub type class TypeName[][]: {'static} [for<'ctx> WithContextLt::MemberType<'ctx>] -} + type T: { } where { + 'ctx: 'a + }; -bijective_higher_ranked_type! { - /// Higher ranked type for borrows `&T`. - /// - /// The borrow gets the `'a` lifetime, not the `'ctx` lifetime. - pub type DynRef['ctx][][T['ctx][]]: WithContextLt['ctx][] - for<'a> - (&'a WithContextLt::T<'a, 'ctx, T>) - (&'a T) - where { - T: ?Sized + type HigherRanked: { 'static }; } } -bijective_higher_ranked_type! { - pub type [][][T[][]]: TypeName[][] - for<'ctx> - (DynRef<'ctx, TypeName::T<'ctx, T>>) - (DynRef<'ctx, T>) - where { - T: ?Sized +pub struct RefHrt<T: ?Sized>(Marker<T>); + +higher_ranked_type! { + impl TypeName { + impl['a, 'ctx, T] type T['a, 'ctx] for RefHrt<T> = + &'a TypeName::T<'a, 'ctx, T> + where { + T: ?Sized + TypeName::LowerForLt<'a, 'ctx, TypeName::Bound<'a, 'ctx>>, + TypeName::T<'a, 'ctx, T>: 'a + }; + + impl['a, 'ctx, T] type HigherRanked['a, 'ctx] for &'a T = + RefHrt<TypeName::HigherRanked<'a, 'ctx, T>> + where { + T: ?Sized + TypeName::LowerType<'a, 'ctx> + }; } } -bijective_higher_ranked_type! { - /// Higher ranked type for mutable borrows `&mut T`. - /// - /// The borrow gets the `'a` lifetime, not the `'ctx` lifetime. - pub type DynMut['ctx][][T['ctx][]]: WithContextLt['ctx][] - for<'a> - (&'a mut WithContextLt::T<'a, 'ctx, T>) - (&'a mut T) - where { - T: ?Sized - } -} - -bijective_higher_ranked_type! { - pub type [][][T[][]]: TypeName[][] - for<'ctx> - (DynMut<'ctx, TypeName::T<'ctx, T>>) - (DynMut<'ctx, T>) - where { - T: ?Sized +pub struct MutHrt<T: ?Sized>(Marker<T>); + +higher_ranked_type! { + impl TypeName { + impl['a, 'ctx, T] type T['a, 'ctx] for MutHrt<T> = + &'a mut TypeName::T<'a, 'ctx, T> + where { + T: ?Sized + TypeName::LowerForLt<'a, 'ctx, TypeName::Bound<'a, 'ctx>>, + TypeName::T<'a, 'ctx, T>: 'a + }; + + impl['a, 'ctx, T] type HigherRanked['a, 'ctx] for &'a mut T = + MutHrt<TypeName::HigherRanked<'a, 'ctx, T>> + where { + T: ?Sized + TypeName::LowerType<'a, 'ctx> + }; } } #[cfg(feature = "alloc")] -bijective_higher_ranked_type! { - /// Higher ranked type for boxes `Box<T>`. - /// - /// A [`Box`] doesn't need either lifetime. - pub type DynBox['ctx][][T['ctx][]]: WithContextLt['ctx][] - for<'a> - (Box<WithContextLt::T<'a, 'ctx, T>>) - (Box<T>) - where { - T: ?Sized - } -} - -#[cfg(feature = "alloc")] -bijective_higher_ranked_type! { - pub type [][][T[][]]: TypeName[][] - for<'ctx> - (DynBox<'ctx, TypeName::T<'ctx, T>>) - (DynBox<'ctx, T>) - where { - T: ?Sized +higher_ranked_type! { + impl TypeName { + impl['a, 'ctx, T] type T['a, 'ctx] for Box<T> = + Box<TypeName::T<'a, 'ctx, T>> + where { + T: ?Sized + TypeName::LowerForLt<'a, 'ctx, TypeName::Bound<'a, 'ctx>>, + }; + + impl['a, 'ctx, T] type HigherRanked['a, 'ctx] for Box<T> = + Box<TypeName::HigherRanked<'a, 'ctx, T>> + where { + T: ?Sized + TypeName::LowerType<'a, 'ctx> + }; } } @@ -119,8 +89,8 @@ bijective_higher_ranked_type! { /// by `id` if [`AnyTrait`] had every trait as a super bound. /// /// ``` -/// use treaty::any::{AnyTrait, any_trait, WithContextLt, TypeName}; -/// use treaty::hkt::bijective_higher_ranked_type; +/// use treaty::any::{AnyTrait, any_trait, TypeName}; +/// use treaty::hkt::higher_ranked_type; /// /// // Create a test value. /// let my_num = MyNum(42); @@ -141,15 +111,16 @@ bijective_higher_ranked_type! { /// fn num(&self) -> i32; /// } /// -/// bijective_higher_ranked_type! { -/// for['ctx] type DynToNum[][]: WithContextLt['ctx][] -/// for<'a> (dyn ToNum + 'a) -/// } +/// enum DynToNum {} +/// +/// higher_ranked_type! { +/// impl TypeName { +/// impl['a, 'ctx] type T['a, 'ctx] for DynToNum = +/// dyn ToNum + 'a; /// -/// // Make the trait object nameable. -/// bijective_higher_ranked_type! { -/// type [][]: TypeName[][] -/// for<'ctx> (DynToNum) +/// impl['a, 'ctx] type HigherRanked['a, 'ctx] for dyn ToNum + 'a = +/// DynToNum; +/// } /// } /// /// // An example struct. @@ -206,9 +177,9 @@ impl<'b, 'ctx: 'b> dyn AnyTrait<'ctx> + Send + 'b { /// as it automatically downcasts the returned [`AnyTraitObject`]. /// /// If the returned [`AnyTraitObject`] is the wrong type, then a panic happens. - pub fn upcast<'a, Trait: ?Sized + TypeName::LowerType<'ctx>>( + pub fn upcast<'a, Trait: ?Sized + TypeName::MemberType>( &'a self, - ) -> Option<&'a WithContextLt::T<'a, 'ctx, Trait>> { + ) -> Option<&'a TypeName::T<'a, 'ctx, Trait>> { self.upcast_to_id(TypeNameId::of::<Trait>()) .map(|object| match object.downcast() { Ok(object) => object, @@ -227,9 +198,9 @@ impl<'b, 'ctx: 'b> dyn AnyTrait<'ctx> + Send + 'b { /// as it automatically downcasts the returned [`AnyTraitObject`]. /// /// If the returned [`AnyTraitObject`] is the wrong type, then a panic happens. - pub fn upcast_mut<'a, Trait: ?Sized + TypeName::LowerType<'ctx>>( + pub fn upcast_mut<'a, Trait: ?Sized + TypeName::MemberType>( &'a mut self, - ) -> Option<&'a mut WithContextLt::T<'a, 'ctx, Trait>> { + ) -> Option<&'a mut TypeName::T<'a, 'ctx, Trait>> { self.upcast_to_id_mut(TypeNameId::of::<Trait>()) .map(|object| match object.downcast() { Ok(object) => object, @@ -273,7 +244,7 @@ macro_rules! any_trait { match id { $(id if id == $crate::any::TypeNameId::of::<$protocol>() => ::core::option::Option::Some($crate::any::AnyTraitObject::<'__, $lt, _>::new::< - $crate::any::WithContextLt::T<'__, $lt, $protocol> + $crate::any::TypeName::T<'__, $lt, $protocol> >(self as _)),)* $id => { $($fallback)* @@ -293,7 +264,7 @@ macro_rules! any_trait { match id { $(id if id == $crate::any::TypeNameId::of::<$protocol>() => ::core::option::Option::Some($crate::any::AnyTraitObject::<'__, $lt, _>::new::< - $crate::any::WithContextLt::T<'__, $lt, $protocol> + $crate::any::TypeName::T<'__, $lt, $protocol> >(self as _)),)* $id => { $($fallback)* @@ -360,10 +331,7 @@ impl<'a, 'ctx, I: Indirect<'a>> AnyTraitObject<'a, 'ctx, I> { /// Type erase a pointer. /// /// `T` doesn't need to be [`Sized`]. As such, a fat pointer can be passed to this function. - pub fn new<T: ?Sized + WithContextLt::LowerType<'a, 'ctx>>(indirect: I::ForT<T>) -> Self - where - WithContextLt::HigherRanked<'a, 'ctx, T>: TypeName::LowerType<'ctx>, - { + pub fn new<T: ?Sized + TypeName::LowerType<'a, 'ctx>>(indirect: I::ForT<T>) -> Self { Self { info: TypeNameId::of_lower::<T>, indirect: RawIndirect::new(indirect), @@ -376,12 +344,9 @@ impl<'a, 'ctx, I: Indirect<'a>> AnyTraitObject<'a, 'ctx, I> { /// /// If the type of the stored value is different, then `self` is /// returned as is. - pub fn downcast<T: ?Sized + WithContextLt::LowerType<'a, 'ctx>>( + pub fn downcast<T: ?Sized + TypeName::LowerType<'a, 'ctx>>( self, - ) -> Result<I::ForT<T>, Self> - where - WithContextLt::HigherRanked<'a, 'ctx, T>: TypeName::LowerType<'ctx>, - { + ) -> Result<I::ForT<T>, Self> { if self.id() == TypeNameId::of_lower::<T>() { // SAFETY: We know that the type name type is unique per T because it is bijective. // A self is only made in Self::new where the info is taken from T. @@ -405,8 +370,6 @@ impl<'a, 'ctx, I: Indirect<'a>> AnyTraitObject<'a, 'ctx, I> { #[cfg(test)] mod test { - use crate::bijective_higher_ranked_type; - use super::*; #[test] @@ -415,12 +378,16 @@ mod test { fn get(&self) -> i32; } - bijective_higher_ranked_type! { - type DynZ['ctx][]: WithContextLt['ctx][] for<'a> (dyn Z<'ctx> + 'a) - } + struct DynZ; - bijective_higher_ranked_type! { - type [][]: TypeName[][] for<'ctx> (DynZ<'ctx>) + higher_ranked_type! { + impl TypeName { + impl['a, 'ctx] type T['a, 'ctx] for DynZ = + dyn Z<'ctx> + 'a; + + impl['a, 'ctx] type HigherRanked['a, 'ctx] for dyn Z<'ctx> + 'a = + DynZ; + } } struct X<'ctx>(&'ctx i32); @@ -433,14 +400,14 @@ mod test { any_trait! { impl['ctx] X<'ctx> = [ - DynZ<'ctx> + DynZ ] } let z = 42; let x = X(&z); let y = (&x as &(dyn AnyTrait<'_> + Send)) - .upcast::<DynZ<'_>>() + .upcast::<DynZ>() .unwrap(); assert_eq!(y.get(), 42); } @@ -461,17 +428,13 @@ mod test { // This proves that the bijective type names are really bijective. fn _is_bijective_raise<'a, 'ctx: 'a, T>( - x: &WithContextLt::T< + x: &TypeName::T< 'a, 'ctx, - TypeName::T< - 'ctx, - TypeName::HigherRanked<'ctx, WithContextLt::HigherRanked<'a, 'ctx, T>>, - >, + TypeName::HigherRanked<'a, 'ctx, T>, >, ) where - T: WithContextLt::LowerType<'a, 'ctx>, - WithContextLt::HigherRanked<'a, 'ctx, T>: TypeName::LowerType<'ctx>, + T: TypeName::LowerType<'a, 'ctx>, { // If C -> B -> A -> B -> C (shown by this assignment), then C and A must be bijective. let _y: &T = x; @@ -480,8 +443,9 @@ mod test { // This proves that the bijective type names are really bijective. fn _is_bijective_lower<'a, 'ctx: 'a, U>( x: &TypeName::HigherRanked< + 'a, 'ctx, - WithContextLt::HigherRanked<'a, 'ctx, WithContextLt::T<'a, 'ctx, TypeName::T<'ctx, U>>>, + TypeName::T<'a, 'ctx, U>, >, ) where U: TypeName::MemberType, |