supply 0.1.0

Provider API for arbitrary number of lifetimes.
Documentation
use core::marker::PhantomData;

use super::{Mut, Ref, Static, Tagged};
use crate::tag::{Tag, WithLt};
use crate::LtList;

macro_rules! impl_static_tagged {
    ($($type:ty),* $(,)?) => {
        $(
            impl Tagged for $type {
                type Tag = Static<$type>;
            }
        )*
    }
}

// Primitives:

// [T; N]
const _: () = {
    #[allow(clippy::type_complexity)]
    pub struct ArrayTag<T: ?Sized, const N: usize>(PhantomData<(fn() -> *const T, [(); N])>);

    impl<L: LtList, T: ?Sized + WithLt<L>, const N: usize> WithLt<L> for ArrayTag<T, N>
    where
        T::Reified: Sized,
    {
        type Reified = [T::Reified; N];
    }

    impl<T: Tagged, const N: usize> Tagged for [T; N] {
        type Tag = ArrayTag<T::Tag, N>;
    }

    impl<T: ?Sized + Tagged + 'static, const N: usize> Tagged for ArrayTag<T, N> {
        type Tag = ArrayTag<T::Tag, N>;
    }

    impl<T: ?Sized + Tag + 'static, const N: usize> Tag for ArrayTag<T, N> {
        type LifetimesTag = T::LifetimesTag;
    }
};

impl_static_tagged![bool];
impl_static_tagged![char];
impl_static_tagged![f32, f64];

// We can't provide a tag for the fn() family of types.

impl_static_tagged![i8, i16, i32, i64, i128, isize];

// *const T
const _: () = {
    impl<T: ?Sized + WithLt<L>, L: LtList> WithLt<L> for *const T {
        type Reified = *const T::Reified;
    }

    impl<T: ?Sized + Tagged> Tagged for *const T {
        type Tag = *const T::Tag;
    }

    impl<T: ?Sized + Tag> Tag for *const T {
        type LifetimesTag = T::LifetimesTag;
    }
};

// *mut T
const _: () = {
    impl<L: LtList, T: ?Sized + WithLt<L>> WithLt<L> for *mut T {
        type Reified = *mut T::Reified;
    }

    impl<T: ?Sized + Tagged> Tagged for *mut T {
        type Tag = *mut T::Tag;
    }

    impl<T: ?Sized + Tag> Tag for *mut T {
        type LifetimesTag = T::LifetimesTag;
    }
};

// &T
impl<'r, T: ?Sized + Tagged> Tagged for &'r T {
    type Tag = Ref<T::Tag>;
}

// &mut T
impl<'r, T: ?Sized + Tagged> Tagged for &'r mut T {
    type Tag = Mut<T::Tag>;
}

// [T]
const _: () = {
    pub struct Slice<T: ?Sized>(PhantomData<fn() -> *const T>);

    impl<L: LtList, T: ?Sized + WithLt<L>> WithLt<L> for Slice<T>
    where
        T::Reified: Sized,
    {
        type Reified = [T::Reified];
    }

    impl<T: ?Sized + Tagged + 'static> Tagged for Slice<T> {
        type Tag = Slice<T::Tag>;
    }

    impl<T: Tagged> Tagged for [T] {
        type Tag = Slice<T::Tag>;
    }

    impl<T: ?Sized + Tag> Tag for Slice<T> {
        type LifetimesTag = T::LifetimesTag;
    }
};

// str
impl_static_tagged![str];

// (...)
const _: () = {
    macro_rules! impl_tuple {
        ($($t:ident),*) => {
            const _: () = {
                pub struct Tuple<$($t: ?Sized),*>(PhantomData<($(fn() -> *const $t,)*)>);

                impl<L: LtList $(, $t: ?Sized + WithLt<L>)*> WithLt<L> for Tuple<$($t,)*>
                where
                    $($t::Reified: Sized,)*
                    ($($t::LifetimesTag,)*): $crate::lt_list::MergeTuple
                {
                    type Reified = ($($t::Reified,)*);
                }

                impl<$($t: Tagged),*> Tagged for ($($t,)*)
                where
                    ($(<$t::Tag as Tag>::LifetimesTag,)*): $crate::lt_list::MergeTuple
                {
                    type Tag = Tuple<$($t::Tag,)*>;

                    // type LifetimesTag = <($($t::LifetimesTag,)*) as $crate::lt_list::MergeTuple>::LtStructure;
                }

                impl<$($t: ?Sized + Tagged),*> Tagged for Tuple<$($t,)*>
                where
                    ($(<$t::Tag as Tag>::LifetimesTag,)*): $crate::lt_list::MergeTuple
                {
                    type Tag = Tuple<$($t::Tag,)*>;

                    // type LifetimesTag = <($($t::LifetimesTag,)*) as $crate::lt_list::MergeTuple>::LtStructure;
                }

                impl<$($t: ?Sized + Tag),*> Tag for Tuple<$($t,)*>
                where
                    ($($t::LifetimesTag,)*): $crate::lt_list::MergeTuple
                {
                    type LifetimesTag = <($($t::LifetimesTag,)*) as $crate::lt_list::MergeTuple>::LtStructure;
                }
            };
        };
    }

    impl_tuple!(); // ()
    impl_tuple!(T);
    impl_tuple!(T0, T1);
    impl_tuple!(T0, T1, T2);
    impl_tuple!(T0, T1, T2, T3);
    impl_tuple!(T0, T1, T2, T3, T4);
    impl_tuple!(T0, T1, T2, T3, T4, T5);
};

impl_static_tagged![u8, u16, u32, u64, u128, usize];