use core::marker::PhantomData;
use core::panic::{RefUnwindSafe, UnwindSafe};
pub trait LtList:
Subset<Self> + Sized + Send + Sync + Unpin + UnwindSafe + RefUnwindSafe + lt_list_seal::Sealed
{
type Head: Subset<Self> + Sized + Send + Sync + Unpin + UnwindSafe + RefUnwindSafe;
type Tail: LtList;
type Tag: ReifyLt<Self, Lifetimes = Self> + 'static;
}
pub type HeadOf<L> = <L as LtList>::Head;
pub type TailOf<L> = <L as LtList>::Tail;
pub type LtTagOf<T> = <T as LtList>::Tag;
mod lt_list_seal {
use super::*;
pub trait Sealed {}
impl Sealed for () {}
impl<'lt, Tail: LtList> Sealed for Lt<'lt, Tail> {}
}
pub type Lt0<L = ()> = L;
pub type Lt1<'l0, L = ()> = Lt<'l0, L>;
pub type Lt2<'l0, 'l1, L = ()> = Lt<'l0, Lt<'l1, L>>;
pub type Lt3<'l0, 'l1, 'l2, L = ()> = Lt<'l0, Lt<'l1, Lt<'l2, L>>>;
pub type Lt4<'l0, 'l1, 'l2, 'l3, L = ()> = Lt<'l0, Lt<'l1, Lt<'l2, Lt<'l3, L>>>>;
pub type Lt5<'l0, 'l1, 'l2, 'l3, 'l4, L = ()> = Lt<'l0, Lt<'l1, Lt<'l2, Lt<'l3, Lt<'l4, L>>>>>;
pub type Lt6<'l0, 'l1, 'l2, 'l3, 'l4, 'l5, L = ()> =
Lt<'l0, Lt<'l1, Lt<'l2, Lt<'l3, Lt<'l4, Lt<'l5, L>>>>>>;
struct Invariant<T>(PhantomData<fn(T) -> T>);
impl LtList for () {
type Head = Lt<'static>;
type Tail = ();
type Tag = ();
}
pub struct Lt<'lt, Tail: LtList = ()>(Invariant<&'lt ()>, PhantomData<fn() -> Tail>);
impl<'lt, Tail: LtList> LtList for Lt<'lt, Tail> {
type Head = Lt<'lt>;
type Tail = Tail;
type Tag = EmptyLt<Tail::Tag>;
}
pub trait LtListStructure: empty_tag_seal::Sealed {
type Tail: LtListStructure;
}
impl LtListStructure for () {
type Tail = ();
}
impl<Tail: LtListStructure> LtListStructure for EmptyLt<Tail> {
type Tail = Tail;
}
mod empty_tag_seal {
use super::*;
pub trait Sealed {}
impl Sealed for () {}
impl<T: Sealed> Sealed for EmptyLt<T> {}
}
pub trait ReifyLt<L: LtList>: LtListStructure {
type Lifetimes: LtList<Tag = Self> + Subset<L>;
}
pub type LifetimesOf<T, L> = <T as ReifyLt<L>>::Lifetimes;
impl<L: LtList> ReifyLt<L> for () {
type Lifetimes = ();
}
pub struct EmptyLt<Tail>(Tail);
impl<'lt, Tail: ReifyLt<L::Tail>, L: LtList<Head = Lt<'lt>>> ReifyLt<L> for EmptyLt<Tail>
where
Lt<'lt, <Tail as ReifyLt<L::Tail>>::Lifetimes>: Subset<L>,
{
type Lifetimes = Lt<'lt, <Tail as ReifyLt<L::Tail>>::Lifetimes>;
}
pub trait Subset<More: lt_list_seal::Sealed>: lt_list_seal::Sealed {}
impl<L: LtList> Subset<L> for () {}
impl Subset<()> for Lt<'static> {}
impl<'lt, Tail: LtList + Subset<L>, L: LtList> Subset<Lt<'lt, L>> for Lt<'lt, Tail> {}
pub trait Merge<L: empty_tag_seal::Sealed>: Sized + empty_tag_seal::Sealed {
type LtStructure: LtListStructure;
}
type M<L1, L2> = <L1 as Merge<L2>>::LtStructure;
impl<L: LtListStructure> Merge<L> for () {
type LtStructure = L;
}
impl<Tail: LtListStructure + Merge<L::Tail>, L: LtListStructure> Merge<L> for EmptyLt<Tail> {
type LtStructure = EmptyLt<<Tail as Merge<L::Tail>>::LtStructure>;
}
pub trait MergeTuple {
type LtStructure: LtListStructure;
}
impl MergeTuple for () {
type LtStructure = ();
}
impl<L: LtListStructure> MergeTuple for (L,) {
type LtStructure = L;
}
impl<L0, L1> MergeTuple for (L0, L1)
where
L0: LtListStructure,
L1: LtListStructure,
L0: Merge<L1>,
{
type LtStructure = M<L0, L1>;
}
impl<L0, L1, L2> MergeTuple for (L0, L1, L2)
where
L0: LtListStructure,
L1: LtListStructure,
L2: LtListStructure,
L0: Merge<L1>,
M<L0, L1>: Merge<L2>,
{
type LtStructure = M<M<L0, L1>, L2>;
}
impl<L0, L1, L2, L3> MergeTuple for (L0, L1, L2, L3)
where
L0: LtListStructure,
L1: LtListStructure,
L2: LtListStructure,
L3: LtListStructure,
L0: Merge<L1>,
M<L0, L1>: Merge<L2>,
M<M<L0, L1>, L2>: Merge<L3>,
{
type LtStructure = M<M<M<L0, L1>, L2>, L3>;
}
impl<L0, L1, L2, L3, L4> MergeTuple for (L0, L1, L2, L3, L4)
where
L0: LtListStructure,
L1: LtListStructure,
L2: LtListStructure,
L3: LtListStructure,
L4: LtListStructure,
L0: Merge<L1>,
M<L0, L1>: Merge<L2>,
M<M<L0, L1>, L2>: Merge<L3>,
M<M<M<L0, L1>, L2>, L3>: Merge<L4>,
{
type LtStructure = M<M<M<M<L0, L1>, L2>, L3>, L4>;
}
impl<L0, L1, L2, L3, L4, L5> MergeTuple for (L0, L1, L2, L3, L4, L5)
where
L0: LtListStructure,
L1: LtListStructure,
L2: LtListStructure,
L3: LtListStructure,
L4: LtListStructure,
L5: LtListStructure,
L0: Merge<L1>,
M<L0, L1>: Merge<L2>,
M<M<L0, L1>, L2>: Merge<L3>,
M<M<M<L0, L1>, L2>, L3>: Merge<L4>,
M<M<M<M<L0, L1>, L2>, L3>, L4>: Merge<L5>,
{
type LtStructure = M<M<M<M<M<L0, L1>, L2>, L3>, L4>, L5>;
}