//! Higher-ranked traits and types.
//!
//! A higher-ranked type is a type that needs a lifetime to be "complete". Consider the following
//! code.
//! ```rs
//! type IntBorrow<'a> = &'a i32;
//! ```
//! What if we could pass just `IntBorrow` around as a type; without it's lifetime.
//! In Rust syntax, this type would be `for<'a> IntBorrow<'a>`. `'a` can be filled in with any
//! lifetime. Sadly, Rust only allows `for<'a>` in trait objects. However, trait object provide
//! enough for us to implement arbitrary hifher-ranked types with some extra effort.
//!
//! In this module the [`bijective_higher_ranked_type!`] macro generates a type that needs a lifetime to
//! be complete. Before a higher-ranked type can be generated we need a higher-ranked trait to
//! describe what behavior the resulting "true" type will have.
//!
//! The [`bijective_higher_ranked_trait!`] macro cgenerates a trait that can be used with
//! [`bijective_higher_ranked_type!`] and as a bound by code wanting to accept a higher ranked type.
//! 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.
use core::marker::PhantomData;
#[derive(Debug, Default, Copy, Clone)]
#[repr(transparent)]
pub struct Invariant<'a>(PhantomData<fn(&'a ()) -> &'a ()>);
#[repr(transparent)]
pub struct Marker<T: ?Sized>(PhantomData<fn() -> *const T>);
impl<T: ?Sized> Copy for Marker<T> {}
impl<T: ?Sized> Clone for Marker<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T: ?Sized> core::fmt::Debug for Marker<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("Marker").finish()
}
}
impl<T: ?Sized> Default for Marker<T> {
fn default() -> Self {
Self(PhantomData)
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! higher_ranked_trait {
{
$vis:vis type class $name:ident$([$($generic:tt)*])? for<$($lt:lifetime),+> <$($for_lt:lifetime),+> {
type Bound = $bound:ty;
type T: {$($lower:tt)*} $(where {$($lower_where:tt)*})?;
type HigherRanked: {$($higher:tt)*} $(where {$($higher_where:tt)*})?;
}
} => {
$vis mod $name {
#![allow(non_snake_case)]
#[allow(unused)]
use super::*;
pub trait LowerForLt<$($lt,)+ $($($generic)*,)? B>
where
$($($lower_where)*)?
$($($higher_where)*)?
{
type T:
RaiseForLt<$($lt,)+ $($($generic)*,)? B, HigherRanked = Self>
+ for<$($for_lt),+> RaiseForLt<$($for_lt,)+ $($($generic)*,)? Bound<$($for_lt,)+ $($($generic)*)?>>
+ ?Sized + $($lower)*;
}
pub trait RaiseForLt<$($lt,)+ $($($generic)*,)? B>
where
$($($lower_where)*)?
$($($higher_where)*)?
{
type HigherRanked:
LowerForLt<$($lt,)+ $($($generic)*,)? B, T = Self>
+ for<$($for_lt),+> LowerForLt<$($for_lt,)+ $($($generic)*,)? Bound<$($for_lt,)+ $($($generic)*)?>>
+ ?Sized + $($higher)*;
}
pub type Bound<$($lt,)+ $($($generic)*)?> = $bound;
pub trait MemberType$(<$($generic)*>)?:
for<$($lt,)+> LowerForLt<$($lt,)+ $($($generic)*,)? Bound<$($lt,)+ $($($generic)*)?>> + $($higher)*
$(where $($higher_where)*)?
{}
impl<$($($generic)*,)? __: ?Sized> MemberType$(<$($generic)*>)? for __
where
__: for<$($lt,)+> LowerForLt<$($lt,)+ $($($generic)*,)? Bound<$($lt,)+ $($($generic)*)?>> + $($higher)?,
$($($higher_where)*)?
{}
pub trait LowerType<$($lt,)+ $($($generic)*)?>:
RaiseForLt<$($lt,)+ $($($generic)*,)? Bound<$($lt,)+ $($($generic)*)?>> + $($lower)*
where
$($($lower_where)*)?
$($($higher_where)*)?
{}
impl<$($lt,)+ $($($generic)*,)? __: ?Sized> LowerType<$($lt,)+ $($($generic)*)?> for __
where
__: RaiseForLt<$($lt,)+ $($($generic)*,)? Bound<$($lt,)+ $($($generic)*)?>> + $($lower)*,
$($($lower_where)*)?
$($($higher_where)*)?
{}
pub type T<$($lt,)+ $($($generic)*,)? __> =
<__ as LowerForLt<$($lt,)+ $($($generic)*,)? Bound<$($lt,)+ $($($generic)*)?>>>::T;
pub type HigherRanked<$($lt,)+ $($($generic)*,)? __> =
<__ as RaiseForLt<$($lt,)+ $($($generic)*,)? Bound<$($lt,)+ $($($generic)*)?>>>::HigherRanked;
//
// pub type HigherRankedAll<$($lt,)+ $($($generic)*,)? __> =
// <__ as RaiseForLtAll<$($($generic)*,)? Bound<$($lt,)+ $($($generic)*)?>>>::HigherRankedAll;
}
}
}
pub use higher_ranked_trait;
#[doc(hidden)]
#[macro_export]
macro_rules! higher_ranked_type {
{
impl $higher_trait:ident {
impl$([$($lower_generic:tt)*])? type T[$($lower_forward:tt)*] for $lower_higher:ty =
$lower:ty
$(where {$($lower_where:tt)*})?;
impl$([$($higher_generic:tt)*])? type HigherRanked[$($higher_lt:lifetime),+]$([$($higher_forward:tt)*])? for $higher_lower:ty =
$higher:ty
$(where {$($higher_where:tt)*})?;
//
// impl$([$($higher_all_generic:tt)*])? type HigherRankedAll[$($higher_all_lt:lifetime),+]$([$($higher_all_forward:tt)*])? for $higher_all_lower:ty =
// $higher_all:ty
// $(where {$($higher_all_where:tt)*})?;
}
} => {
impl$(<$($lower_generic)*>)* $higher_trait::LowerForLt<$($lower_forward)*, $higher_trait::Bound<$($lower_forward)*>> for $lower_higher
$(where $($lower_where)*)?
{
type T = $lower;
}
impl$(<$($higher_generic)*>)* $higher_trait::RaiseForLt<$($higher_lt,)+ $($($higher_forward)*,)? $higher_trait::Bound<$($higher_lt,)+ $($($higher_forward)*)?>> for $higher_lower
$(where $($higher_where)*)?
{
type HigherRanked = $higher;
}
//
// impl$(<$($higher_all_generic)*>)* $higher_trait::RaiseForLtAll<$($($higher_all_forward)*,)? $higher_trait::Bound<$($higher_all_lt,)+ $($($higher_all_forward)*)?>> for $higher_all_lower
// $(where $($higher_all_where)*)?
// {
// type HigherRankedAll = $higher_all;
// }
}
}
pub use higher_ranked_type;
// #[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);
// }
// }
// }