mod tag_type_id;
mod tagged;
use core::marker::PhantomData;
pub use tag_type_id::TagTypeId;
use crate::lt_list::{Cons, FirstN, Hole, Inv, LtHoleList, LtList, Prefix};
pub trait Tagged {
type Tag: ?Sized + Tag + Tagged<Tag = Self::Tag> + 'static;
}
pub trait Tag {
type LifetimesTag: LtHoleList + 'static;
}
pub trait Reify<L: LtList>: reify_seal::Sealed<L> + Tagged<Tag = Self::UsedTag> {
type Reified: ?Sized;
type Lifetimes: LtList + Prefix<L>;
type UsedTag: ?Sized
+ Tagged<Tag = Self::UsedTag>
+ Tag<LifetimesTag = Self::UsedLifetimesTag>
+ WithLt<Self::Lifetimes, Reified = Self::Reified>
+ 'static;
type UsedLifetimesTag: FirstN<Self::Lifetimes, Lifetimes = Self::Lifetimes>
+ FirstN<L, Lifetimes = Self::Lifetimes>
+ 'static;
}
pub trait ReifySized<L: LtList>: Reify<L, Reified = Self::SizedReified> {
type SizedReified;
}
impl<L: LtList, T: ?Sized + Reify<L>> ReifySized<L> for T
where
T::Reified: Sized,
{
type SizedReified = T::Reified;
}
type LifetimesOf<T, L> = <T as FirstN<L>>::Lifetimes;
impl<T, L> Reify<L> for T
where
T: ?Sized + Tagged,
L: LtList,
LifetimesTagOf<T::Tag>: FirstN<L>,
LifetimesTagOf<T::Tag>: FirstN<
LifetimesOf<LifetimesTagOf<T::Tag>, L>,
Lifetimes = LifetimesOf<LifetimesTagOf<T::Tag>, L>,
>,
T::Tag: WithLt<LifetimesOf<LifetimesTagOf<T::Tag>, L>>,
{
type Reified = ReifiedOf<T::Tag, LifetimesOf<LifetimesTagOf<T::Tag>, L>>;
type Lifetimes = LifetimesOf<LifetimesTagOf<T::Tag>, L>;
type UsedTag = T::Tag;
type UsedLifetimesTag = LifetimesTagOf<T::Tag>;
}
mod reify_seal {
use super::*;
pub trait Sealed<L: LtList> {}
impl<L, T> Sealed<L> for T
where
T: ?Sized + Tagged,
L: LtList,
LifetimesTagOf<T::Tag>: FirstN<L>,
LifetimesTagOf<T::Tag>: FirstN<
LifetimesOf<LifetimesTagOf<T::Tag>, L>,
Lifetimes = LifetimesOf<LifetimesTagOf<T::Tag>, L>,
>,
T::Tag: WithLt<LifetimesOf<LifetimesTagOf<T::Tag>, L>>,
{
}
}
pub type TagOf<T> = <T as Tagged>::Tag;
pub type LifetimesTagOf<T> = <T as Tag>::LifetimesTag;
pub type ReifiedOf<T, L> = <T as WithLt<L>>::Reified;
pub trait WithLt<L: LtList>: Tag + Tagged<Tag = Self> + 'static {
type Reified: ?Sized;
}
#[allow(clippy::type_complexity)]
pub struct DynTag<LT, T: ?Sized>(PhantomData<(fn() -> *const T, LT)>);
pub trait TagDef<L: LtList>: 'static {
type T: ?Sized;
}
impl<Def: ?Sized + TagDef<L>, L: LtList, LT: FirstN<L, Lifetimes = L> + 'static> WithLt<L>
for DynTag<LT, Def>
{
type Reified = Def::T;
}
impl<Def: ?Sized + 'static, LT: LtHoleList + 'static> Tagged for DynTag<LT, Def> {
type Tag = Self;
}
impl<Def: ?Sized + 'static, LT: LtHoleList + 'static> Tag for DynTag<LT, Def> {
type LifetimesTag = LT;
}
pub type Static<T> = tag_for!(T);
pub struct AddLt<T: ?Sized>(PhantomData<fn() -> *const T>);
impl<T: ?Sized + WithLt<L::Tail>, L: LtList> WithLt<L> for AddLt<T> {
type Reified = T::Reified;
}
impl<T: ?Sized + Tagged> Tagged for AddLt<T> {
type Tag = AddLt<T::Tag>;
}
impl<T: ?Sized + Tag> Tag for AddLt<T> {
type LifetimesTag = Cons<Hole, T::LifetimesTag>;
}
pub struct Ref<T: ?Sized>(PhantomData<fn() -> T>);
impl<'r, T: ?Sized + WithLt<L>, L: LtList<Head = Inv<'r>>> WithLt<L> for Ref<T>
where
T::Reified: 'r,
{
type Reified = &'r T::Reified;
}
impl<T: ?Sized + Tagged> Tagged for Ref<T> {
type Tag = Ref<T::Tag>;
}
impl<T: ?Sized + Tag> Tag for Ref<T> {
type LifetimesTag = T::LifetimesTag;
}
pub struct Mut<T: ?Sized>(PhantomData<fn() -> T>);
impl<'r, T: ?Sized + WithLt<L>, L: LtList<Head = Inv<'r>>> WithLt<L> for Mut<T>
where
T::Reified: 'r,
{
type Reified = &'r 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;
}
#[doc(hidden)]
#[macro_export]
macro_rules! tag_for {
(<$l0:lifetime, $l1:lifetime, $l2:lifetime $(,)?> $type:ty) => {
$crate::tag::DynTag<$crate::lt_list::LtH3, dyn for<$l0, $l1, $l2> $crate::tag::TagDef<$crate::lt_list::Lt3<$l0, $l1, $l2>, T = $type>>
};
(<$l0:lifetime, $l1:lifetime $(,)?> $type:ty) => {
$crate::tag::DynTag<$crate::lt_list::LtH2, dyn for<$l0, $l1> $crate::tag::TagDef<$crate::lt_list::Lt2<$l0, $l1>, T = $type>>
};
(<$l0:lifetime $(,)?> $type:ty) => {
$crate::tag::DynTag<$crate::lt_list::LtH1, dyn for<$l0> $crate::tag::TagDef<$crate::lt_list::Lt1<$l0>, T = $type>>
};
($type:ty) => {
$crate::tag::DynTag<$crate::lt_list::LtH0, dyn $crate::tag::TagDef<$crate::lt_list::Lt0, T = $type>>
};
}
#[doc(inline)]
pub use tag_for;
#[doc(hidden)]
#[macro_export]
macro_rules! impl_tagged {
(
$vis:vis struct $name:ident< $($tail:tt)*
) => {
$crate::impl_tagged! {
@scan_generic
{
$vis struct $name
}
()
()
()
()
()
{$($tail)*}
}
};
(
@scan_generic
{$($struct:tt)*}
($($generics:tt)*)
($($reify_generics:tt)*)
($($lt_generics:tt)*)
($($tag_generics:tt)*)
($($const_generics:tt)*)
{$(,)? $generic:ident $(,)? $($tail:tt)*}
) => {
$crate::impl_tagged! {
@scan_generic
{$($struct)*}
($($generics)* $generic,)
($($reify_generics)* $generic::Reified,)
($($lt_generics)*)
($($tag_generics)* $generic,)
($($const_generics)*)
{$($tail)*}
}
};
(
@scan_generic
{$($struct:tt)*}
($($generics:tt)*)
($($reify_generics:tt)*)
($($lt_generics:tt)*)
($($tag_generics:tt)*)
($($const_generics:tt)*)
{$(,)? $lt:lifetime $($tail:tt)*}
) => {
$crate::impl_tagged! {
@scan_generic
{$($struct)*}
($($generics)* $lt,)
($($reify_generics)* $lt,)
($($lt_generics)* $lt,)
($($tag_generics)*)
($($const_generics)*)
{$($tail)*}
}
};
(
@scan_generic
{
$vis:vis struct $name:ident
}
($($generics:tt)*)
($($reify_generics:tt)*)
($($lt_generic:lifetime,)*)
($($tag_generic:ident,)*)
($($const_generics:tt)*)
{$(,)? > $(where $($where:tt)*)?}
) => {
const _: () = {
$vis struct Tag<$($tag_generic: ?Sized)*>(::core::marker::PhantomData<fn() -> ($(*const $tag_generic,)*)>);
impl<$($generics)*> Tagged for $name<$($generics)*>
where
$($tag_generic: Tagged,)*
{
type Tag = Tag<$($tag_generic::Tag)*>;
}
impl<$($lt_generic,)* $($tag_generic,)* L: LtList> WithLt<$crate::impl_tagged!(@lifetime $($lt_generic,)* L)> for Tag<$($tag_generic,)*>
where
$($tag_generic: ?Sized + WithLt<L>,)*
$($tag_generic::Reified: Sized,)*
$($($where)*)?
{
type Reified = $name<$($reify_generics)*>;
}
impl<$($tag_generic: ?Sized + Tagged,)*> Tagged for Tag<$($tag_generic,)*> {
type Tag = Tag<$($tag_generic::Tag)*>;
}
impl<$($tag_generic: ?Sized + supply::tag::Tag,)*> supply::tag::Tag for Tag<$($tag_generic,)*> {
type LifetimesTag = $crate::impl_tagged!(@lifetime_tag $($lt_generic,)* <($($tag_generic::LifetimesTag,)*) as supply::lt_list::Longest>::Holes);
}
};
};
(
@lifetime $l0:lifetime, $L:ty
) => {
$crate::lt_list::Lt1<$l0, $L>
};
(
@lifetime_tag $l0:lifetime, $L:ty
) => {
$crate::lt_list::LtH0<$L>
};
(
@lifetime $L:ty
) => {
$L
};
(
@lifetime_tag $L:ty
) => {
$L
};
}
#[doc(inline)]
pub use impl_tagged;