Diffstat (limited to 'src/hkt.rs')
| -rw-r--r-- | src/hkt.rs | 261 |
1 files changed, 107 insertions, 154 deletions
@@ -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); +// } +// } +// } |