Diffstat (limited to 'src/hkt.rs')
-rw-r--r--src/hkt.rs261
1 files changed, 107 insertions, 154 deletions
diff --git a/src/hkt.rs b/src/hkt.rs
index 83a051e..f51ebed 100644
--- a/src/hkt.rs
+++ b/src/hkt.rs
@@ -19,82 +19,31 @@
//! Bounding a generic by a higher-ranked trait simultaniously allows any higher-ranked type with
//! a "true" type with the required traits and any lifetime to be given to that "true" type.
-/// Used to cause `'lt` to have extra bounds when using `for<'lt>` syntax.
-///
-/// Including this type where a `for<'lt>` is being generated will result in the following bounds
-/// being applied.
-/// * `'bound: 'lt` - `'lt` will **not** outlive `'bound`.
-/// * `T: 'lt` - `T` will outlive `'lt`.
-pub type Bound<'lt, 'bound, T = ()> = (&'lt &'bound (), &'lt T);
+#[derive(Debug, Default, Copy, Clone)]
+#[repr(transparent)]
+pub struct Invariant<'a>(PhantomData<fn(&'a ()) -> &'a ()>);
-/// Generate a higher-ranked trait.
-#[doc(hidden)]
-#[macro_export]
-macro_rules! higher_ranked_trait {
- {
- $vis:vis type class $name:ident[$ctx:lifetime $(, $($generic:tt)*)?]: [for<$lt:lifetime> $($($provides:tt)+)?]
- $(where {
- $($bound:tt)*
- })?
- $(for where {
- $($for_bound:tt)*
- })?
- } => {
- $vis mod $name {
- #![allow(unused, non_snake_case)]
-
- use super::*;
-
- pub trait ForLt<$lt, $ctx: $lt, B $(, $($generic)*)?>
- where $($($bound)*)? $($($for_bound)*)?
-
- {
- type T: $lt $(+ $($provides)+)?;
- }
-
- pub trait Trait<$ctx $(, $($generic)*)?>: for<$lt> ForLt<$lt, $ctx, $crate::hkt::Bound<$lt, $ctx $(, $($generic)*)?> $(, $($generic)*)?>
- where
- $($($bound)*)?
- {}
-
- impl<$ctx, ____ $(, $($generic)*)?> Trait<$ctx $(, $($generic)*)?> for ____
- where
- ____: for<$lt> ForLt<$lt, $ctx, $crate::hkt::Bound<$lt, $ctx $(, $($generic)*)?> $(, $($generic)*)?>,
- $($($bound)*)?
- {}
+#[repr(transparent)]
+pub struct Marker<T>(PhantomData<fn() -> T>);
- pub type T<$lt, $ctx, H $(, $($generic)*)?> = <H as ForLt<$lt, $ctx, $crate::hkt::Bound<$lt, $ctx $(, $($generic)*)?> $(, $($generic)*)?>>::T;
- }
- };
+impl<T> Copy for Marker<T> {}
+impl<T> Clone for Marker<T> {
+ fn clone(&self) -> Self {
+ *self
+ }
}
-use core::marker::PhantomData;
-
-#[doc(inline)]
-pub use higher_ranked_trait;
-
-/// Generate a higher-ranked type.
-#[doc(hidden)]
-#[macro_export]
-macro_rules! higher_ranked_type {
- {
- $vis:vis type $name:ident[$ctx:lifetime $(, $($generic:tt)*)?]: ($($type_class:tt)*)$([$($type_class_generic:tt)*])?
- $(where {$($bound:tt)*})?
- = for<$lt:lifetime> $for_lt_type:ty
- $(where {$($higher_bound:tt)*})?
- } => {
- $vis struct $name<$ctx $(, $($generic)*)?>(core::marker::PhantomData<fn() -> (&$ctx (), $($($generic)*)?)>);
-
- impl<$lt, $ctx $(, $($generic)*)?> $($type_class)*::ForLt<$lt, $ctx, $crate::hkt::Bound<$lt, $ctx $(, $($generic)*)?> $(, $($type_class_generic)*)?> for $name<$ctx $(, $($generic)*)?>
- where $($($bound)*)? $($($higher_bound)*)?
- {
- type T = $for_lt_type;
- }
+impl<T> core::fmt::Debug for Marker<T> {
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ f.debug_tuple("Marker").finish()
}
}
-#[doc(inline)]
-pub use higher_ranked_type;
+impl<T> Default for Marker<T> {
+ fn default() -> Self {
+ Self(PhantomData)
+ }
+}
#[doc(hidden)]
#[macro_export]
@@ -139,7 +88,7 @@ macro_rules! bijective_higher_ranked_trait {
type T: ?Sized + RaiseForLt<
$lt,
$($lifetimes,)*
- &$lt ($(&$lifetimes (),)* $($generic),*),
+ &$lt ($(&$lifetimes (),)* $(*const $generic,)*),
$($generic,)*
HigherRanked = Self
> $(+ $($provides)+)? + $lt;
@@ -163,7 +112,7 @@ macro_rules! bijective_higher_ranked_trait {
type HigherRanked: ?Sized + LowerForLt<
$lt,
$($lifetimes,)*
- &$lt ($(&$lifetimes (),)* $($generic),*),
+ &$lt ($(&$lifetimes (),)* $(*const $generic,)*),
$($generic,)*
T = Self
> $(+ $lifetimes)*;
@@ -181,7 +130,7 @@ macro_rules! bijective_higher_ranked_trait {
$($lifetimes,)*
// Use a implied bound to make sure the lifetime from the for syntax is
// correctly bounded.
- &$lt ($(&$lifetimes (),)* $($generic),*),
+ &$lt ($(&$lifetimes (),)* $(*const $generic,)*),
$($generic),*
>
where
@@ -198,7 +147,7 @@ macro_rules! bijective_higher_ranked_trait {
__: for<$lt> LowerForLt<
$lt,
$($lifetimes,)*
- &$lt ($(&$lifetimes (),)* $($generic),*),
+ &$lt ($(&$lifetimes (),)* $(*const $generic,)*),
$($generic),*
>,
$($($bound)*)?
@@ -209,7 +158,7 @@ macro_rules! bijective_higher_ranked_trait {
<__ as LowerForLt<
$lt,
$($lifetimes,)*
- &$lt ($(&$lifetimes (),)* $($generic),*),
+ &$lt ($(&$lifetimes (),)* $(*const $generic,)*),
$($generic),*
>>::T;
@@ -226,7 +175,7 @@ macro_rules! bijective_higher_ranked_trait {
>: RaiseForLt<
$lt,
$($lifetimes,)*
- &$lt ($(&$lifetimes (),)* $($generic),*),
+ &$lt ($(&$lifetimes (),)* $(*const $generic,)*),
$($generic),*
> $(+ $($provides)+)?
where
@@ -244,7 +193,7 @@ macro_rules! bijective_higher_ranked_trait {
__: RaiseForLt<
$lt,
$($lifetimes,)*
- &$lt ($(&$lifetimes (),)* $($generic),*),
+ &$lt ($(&$lifetimes (),)* $(*const $generic,)*),
$($generic),*
> $(+ $($provides)+)?,
$($($bound)*)?
@@ -255,13 +204,15 @@ macro_rules! bijective_higher_ranked_trait {
<__ as RaiseForLt<
$lt,
$($lifetimes,)*
- &$lt ($(&$lifetimes (),)* $($generic),*),
+ &$lt ($(&$lifetimes (),)* $(*const $generic,)*),
$($generic),*
>>::HigherRanked;
}
};
}
+use core::marker::PhantomData;
+
#[doc(inline)]
pub use bijective_higher_ranked_trait;
@@ -271,7 +222,7 @@ pub use bijective_higher_ranked_trait;
macro_rules! bijective_higher_ranked_type {
{
$(#[$($meta:tt)*])*
- $vis:vis type $name:ident[
+ $vis:vis $(for[$($extra_lt:lifetime)*])? type $name:ident[
$($ctx:lifetime),*
][
$($generic:ident),*
@@ -285,12 +236,12 @@ macro_rules! bijective_higher_ranked_type {
} => {
$(#[$($meta)*])*
$vis struct $name<
- $($type_class_lifetime,)*
+ $($ctx,)*
$($generic: ?Sized,)*
$($($forwarding_generic: ?Sized),*)?
>(
core::marker::PhantomData<fn() -> (
- $(&$type_class_lifetime (),)*
+ $(&$ctx (),)*
$(*const $generic,)*
$($(*const $forwarding_generic,)*)?
)>
@@ -298,6 +249,7 @@ macro_rules! bijective_higher_ranked_type {
impl<
$lt,
+ $($($extra_lt,)*)?
$($ctx,)*
$($generic,)*
$($($forwarding_generic),*)?
@@ -310,7 +262,7 @@ macro_rules! bijective_higher_ranked_type {
),
$($type_class_generic),*
> for $name<
- $($type_class_lifetime,)*
+ $($ctx,)*
$($generic,)*
$($($forwarding_generic),*)?
>
@@ -322,7 +274,7 @@ macro_rules! bijective_higher_ranked_type {
&$lt (
$(&$forward_lt (),)*
$(*const $forward_generic,)*
- )
+ ),
$($forward_generic,)*
>,
)*)?
@@ -333,6 +285,7 @@ macro_rules! bijective_higher_ranked_type {
impl<
$lt,
+ $($($extra_lt,)*)?
$($ctx,)*
$($generic,)*
$($($forwarding_generic),*)?
@@ -353,14 +306,14 @@ macro_rules! bijective_higher_ranked_type {
&$lt (
$(&$forward_lt (),)*
$(*const $forward_generic,)*
- )
+ ),
$($forward_generic,)*
>,
)*)?
$($($bound)*)?
{
type HigherRanked = $name<
- $($type_class_lifetime,)*
+ $($ctx,)*
$($generic,)*
$($(
<$forwarding_generic as $type_class::RaiseForLt<
@@ -369,7 +322,7 @@ macro_rules! bijective_higher_ranked_type {
&$lt (
$(&$forward_lt (),)*
$(*const $forward_generic,)*
- )
+ ),
$($forward_generic,)*
>>::HigherRanked
),*)?
@@ -377,7 +330,7 @@ macro_rules! bijective_higher_ranked_type {
}
};
{
- $vis:vis type [
+ $vis:vis $(for[$($extra_lt:lifetime)*])? type [
$($ctx:lifetime),*
][
$($generic:ident),*
@@ -391,7 +344,7 @@ macro_rules! bijective_higher_ranked_type {
} => {
const _: () = {
$crate::hkt::bijective_higher_ranked_type! {
- $vis type __HigherRanked[
+ $vis $(for[$($extra_lt)*])? type __HigherRanked[
$($ctx),*
][
$($generic),*
@@ -407,7 +360,7 @@ macro_rules! bijective_higher_ranked_type {
};
{
$(#[$($meta:tt)*])*
- $vis:vis type $name:ident[
+ $vis:vis $(for[$($extra_lt:lifetime)*])? type $name:ident[
$($ctx:lifetime),*
][
$($generic:ident),*
@@ -420,7 +373,7 @@ macro_rules! bijective_higher_ranked_type {
} => {
$crate::hkt::bijective_higher_ranked_type! {
$(#[$($meta)*])*
- $vis type $name[
+ $vis $(for[$($extra_lt)*])? type $name[
$($ctx),*
][
$($generic),*
@@ -438,70 +391,70 @@ macro_rules! bijective_higher_ranked_type {
#[doc(inline)]
pub use bijective_higher_ranked_type;
-higher_ranked_trait! {
- pub type class AnySend['ctx]: [for<'lt> Send]
+bijective_higher_ranked_trait! {
+ pub type class AnySizedSend[][]: [for<'lt> Send + Sized]
}
-#[cfg(test)]
-mod test {
- use super::*;
-
- /// Some trait with two lifetimes and a generic.
- trait Demo<'lt, 'ctx, T: Send + 'lt> {
- fn add(&self, x: &'lt &'ctx i32) -> i32;
- }
-
- impl<'lt, 'ctx, T: Send + 'lt> Demo<'lt, 'ctx, T> for i32 {
- fn add(&self, x: &'lt &'ctx i32) -> i32 {
- self + **x
- }
- }
-
- impl<'lt, 'ctx, T: Send + 'lt> Demo<'lt, 'ctx, T> for &'lt (dyn Demo<'lt, 'ctx, T> + 'lt) {
- fn add(&self, x: &'lt &'ctx i32) -> i32 {
- (**self).add(x)
- }
- }
-
- // Higher-ranked trait that requires the "true" type to implement Demo.
- higher_ranked_trait! {
- type class Any['ctx, T]: [for<'lt> Demo<'lt, 'ctx, T>]
- where {
- T: Send,
- }
- for where {
- T: 'lt
- }
- }
-
- // Higher-ranked type with a "true" type of a borrow of a trait object.
- // The complex part to support here is the `+ 'lt`.
- // This entire module is specialized to support this usecase because that is what treaty needs
- // for it's API.
- higher_ranked_type! {
- type X['ctx, T]: (Any)[T]
- where {
- T: Send,
- } = for<'lt> &'lt (dyn Demo<'lt, 'ctx, T> + 'lt)
- }
-
- // We bound the generic T by the higher-ranked trait Any.
- //
- // We then inject a 'lt into the higher-ranked type to get a "true" type.
- fn demo<'lt, 'ctx, T: Any::Trait<'ctx, i32>>(x: Any::T<'lt, 'ctx, T, i32>, y: &'lt &'ctx i32) {
- assert_eq!(x.add(y), 10);
- }
-
- #[test]
- fn can_use_hkt() {
- let ctx = 2;
- let ctx = &ctx;
-
- {
- // The lifetimes here can't be 'static because local isn't static even though z could be.
- let local = &ctx;
- let z: &dyn Demo<'_, '_, i32> = &8i32;
- demo::<X<'_, i32>>(z, local);
- }
- }
-}
+// #[cfg(test)]
+// mod test {
+// use super::*;
+//
+// /// Some trait with two lifetimes and a generic.
+// trait Demo<'lt, 'ctx, T: Send + 'lt> {
+// fn add(&self, x: &'lt &'ctx i32) -> i32;
+// }
+//
+// impl<'lt, 'ctx, T: Send + 'lt> Demo<'lt, 'ctx, T> for i32 {
+// fn add(&self, x: &'lt &'ctx i32) -> i32 {
+// self + **x
+// }
+// }
+//
+// impl<'lt, 'ctx, T: Send + 'lt> Demo<'lt, 'ctx, T> for &'lt (dyn Demo<'lt, 'ctx, T> + 'lt) {
+// fn add(&self, x: &'lt &'ctx i32) -> i32 {
+// (**self).add(x)
+// }
+// }
+//
+// // Higher-ranked trait that requires the "true" type to implement Demo.
+// bijective_higher_ranked_trait! {
+// type class Any['ctx, T]: [for<'lt> Demo<'lt, 'ctx, T>]
+// where {
+// T: Send,
+// }
+// for where {
+// T: 'lt
+// }
+// }
+//
+// // Higher-ranked type with a "true" type of a borrow of a trait object.
+// // The complex part to support here is the `+ 'lt`.
+// // This entire module is specialized to support this usecase because that is what treaty needs
+// // for it's API.
+// higher_ranked_type! {
+// type X['ctx, T]: (Any)[T]
+// where {
+// T: Send,
+// } = for<'lt> &'lt (dyn Demo<'lt, 'ctx, T> + 'lt)
+// }
+//
+// // We bound the generic T by the higher-ranked trait Any.
+// //
+// // We then inject a 'lt into the higher-ranked type to get a "true" type.
+// fn demo<'lt, 'ctx, T: Any::Trait<'ctx, i32>>(x: Any::T<'lt, 'ctx, T, i32>, y: &'lt &'ctx i32) {
+// assert_eq!(x.add(y), 10);
+// }
+//
+// #[test]
+// fn can_use_hkt() {
+// let ctx = 2;
+// let ctx = &ctx;
+//
+// {
+// // The lifetimes here can't be 'static because local isn't static even though z could be.
+// let local = &ctx;
+// let z: &dyn Demo<'_, '_, i32> = &8i32;
+// demo::<X<'_, i32>>(z, local);
+// }
+// }
+// }