Diffstat (limited to 'src/any.rs')
-rw-r--r--src/any.rs214
1 files changed, 89 insertions, 125 deletions
diff --git a/src/any.rs b/src/any.rs
index 488f6f3..3207f02 100644
--- a/src/any.rs
+++ b/src/any.rs
@@ -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,