rust-spec 0.7.1

Classification of types in accordance with the Rust specification
Documentation
use core::ops::Add;

use crate::{Max, Maximum, NonOpaque, RustSpec, Sum, Unstable, drop::NeedsDrop, layout::Robust};

macro_rules! impl_tuple_type_spec {
    (@alignment $ty:ident) => {
        <$ty as RustSpec>::__Alignment
    };
    (@alignment $head:ident, $($tail:ident),+) => {
        Maximum<<$head as RustSpec>::__Alignment, impl_tuple_type_spec!(@alignment $($tail),+)>
    };
    (@kind $axis:ident; $ty:ident) => {
        <$ty as RustSpec>::$axis
    };
    (@kind $axis:ident; $head:ident, $($tail:ident),+) => {
        Sum<<$head as RustSpec>::$axis, impl_tuple_type_spec!(@kind $axis; $($tail),+)>
    };

    (@params for $target:ty [$($all:ident),+] [$($params:tt)*]; $ty:ident) => {
        unsafe impl<$($all),+> RustSpec for $target
        where
            $($params)*
            $ty: RustSpec + ?Sized,
            Robust: Add<impl_tuple_type_spec!(@kind Trap; $($all),+)>,
            impl_tuple_type_spec!(@kind Drop; $($all),+): crate::drop::DropKind,
        {
            type Layout = Unstable;
            type Size = impl_tuple_type_spec!(@kind Size; $($all),+);
            type __Alignment = impl_tuple_type_spec!(@alignment $($all),+);
            type Trap = Sum<Robust, impl_tuple_type_spec!(@kind Trap; $($all),+)>;
            type Niche = impl_tuple_type_spec!(@kind Niche; $($all),+);
            type Drop = NeedsDrop<impl_tuple_type_spec!(@kind Drop; $($all),+)>;
            type Mutability = impl_tuple_type_spec!(@kind Mutability; $($all),+);
            type Opacity = NonOpaque;
            type __IndirectTrap = impl_tuple_type_spec!(@kind __IndirectTrap; $($all),+);
        }
    };
    (@params for $target:ty [$($all:ident),+] [$($params:tt)*]; $head:ident, $($tail:ident),+) => {
        impl_tuple_type_spec!(
            @params for $target
            [$($all),+]
            [$($params)*
                $head: RustSpec<
                    Size: Add<impl_tuple_type_spec!(@kind Size; $($tail),+)>,
                    __Alignment: Max<
                        impl_tuple_type_spec!(@alignment $($tail),+),
                    >,
                    Trap: Add<impl_tuple_type_spec!(@kind Trap; $($tail),+)>,
                    Niche: Add<impl_tuple_type_spec!(@kind Niche; $($tail),+)>,
                    Drop: Add<impl_tuple_type_spec!(@kind Drop; $($tail),+)>,
                    Mutability: Add<impl_tuple_type_spec!(@kind Mutability; $($tail),+)>,
                    __IndirectTrap: Add<impl_tuple_type_spec!(@kind __IndirectTrap; $($tail),+)>,
                >,
            ]
            ; $($tail),+
        );
    };

    ($(($($ty:ident),+)),+ $(,)?) => { $(
        impl_tuple_type_spec!(@params for ($($ty,)+) [$($ty),+] []; $($ty),+); )+
    };
}

impl_tuple_type_spec! {
    (A),
    (A, B),
    (A, B, C),
    (A, B, C, D),
    (A, B, C, D, E),
    (A, B, C, D, E, F),
    (A, B, C, D, E, F, G),
    (A, B, C, D, E, F, G, H),
    (A, B, C, D, E, F, G, H, I),
    (A, B, C, D, E, F, G, H, I, J),
    (A, B, C, D, E, F, G, H, I, J, K),
    (A, B, C, D, E, F, G, H, I, J, K, L)
}

#[cfg(test)]
mod tests {
    #[cfg(feature = "alloc")]
    use alloc::{boxed::Box, vec::Vec};
    use core::num::NonZero as StdNonZero;

    use static_assertions::assert_impl_all;

    use super::*;
    use crate::{
        Stable,
        layout::NonRobust,
        mutability::{Exclusive, WithoutInterior},
        niche::{WithNiche, WithoutNiche},
        size::{self, Zero},
    };

    #[test]
    fn tuple_size_family_tracks_zst_fields() {
        assert_impl_all!(((), ()):
            RustSpec<
                Layout = Unstable,
                Size = size::Sized<Zero>,
                __Alignment = crate::One,
                Trap = Robust,
                Niche = WithoutNiche,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = Robust,
            >,
        );
        assert_impl_all!(((), (), ()):
            RustSpec<
                Layout = Unstable,
                Size = size::Sized<Zero>,
                __Alignment = crate::One,
                Trap = Robust,
                Niche = WithoutNiche,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = Robust,
            >,
        );
    }

    #[test]
    fn tuple_size_family_tracks_non_zst_fields() {
        assert_impl_all!(((), u8):
            RustSpec<
                Layout = Unstable,
                Size = crate::size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = crate::One,
                Trap = Robust,
                Niche = WithoutNiche,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = Robust,
            >,
        );
        assert_impl_all!((u8, ()):
            RustSpec<
                Layout = Unstable,
                Size = crate::size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = crate::One,
                Trap = Robust,
                Niche = WithoutNiche,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = Robust,
            >,
        );
        assert_impl_all!(((), u8, ()):
            RustSpec<
                Layout = Unstable,
                Size = crate::size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = crate::One,
                Trap = Robust,
                Niche = WithoutNiche,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = Robust,
            >,
        );
    }

    #[test]
    fn stored_tuple_3_without_niche() {
        assert_impl_all!((u8, u8, u8):
            RustSpec<
                Layout = Unstable,
                Size = size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = crate::One,
                Trap = Robust,
                Niche = WithoutNiche,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = Robust,
            >,
        );

        assert_impl_all!(&(u8, u8, u8):
            RustSpec<
                Layout = Unstable,
                Size = size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = <usize as RustSpec>::__Alignment,
                Trap = NonRobust,
                Niche = WithNiche<Stable>,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = Robust,
            >,
        );
        assert_impl_all!(&mut (u8, u8, u8):
            RustSpec<
                Layout = Unstable,
                Size = size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = <usize as RustSpec>::__Alignment,
                Trap = NonRobust,
                Niche = WithNiche<Stable>,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = Robust,
            >,
        );
        #[cfg(feature = "alloc")]
        assert_impl_all!(Box<(u8, u8, u8)>:
            RustSpec<
                Layout = Unstable,
                Size = size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = <usize as RustSpec>::__Alignment,
                Trap = NonRobust,
                Niche = WithNiche<Stable>,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = Robust,
            >,
        );
        #[cfg(feature = "alloc")]
        assert_impl_all!(&[(u8, u8, u8)]:
            RustSpec<
                Layout = Unstable,
                Size = size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = <usize as RustSpec>::__Alignment,
                Trap = NonRobust,
                Niche = WithNiche<Unstable>,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = Robust,
            >,
        );
        #[cfg(feature = "alloc")]
        assert_impl_all!(&mut [(u8, u8, u8)]:
            RustSpec<
                Layout = Unstable,
                Size = size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = <usize as RustSpec>::__Alignment,
                Trap = NonRobust,
                Niche = WithNiche<Unstable>,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = Robust,
            >,
        );
        #[cfg(feature = "alloc")]
        assert_impl_all!(Box<[(u8, u8, u8)]>:
            RustSpec<
                Layout = Unstable,
                Size = size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = <usize as RustSpec>::__Alignment,
                Trap = NonRobust,
                Niche = WithNiche<Unstable>,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = Robust,
            >,
        );
        #[cfg(feature = "alloc")]
        assert_impl_all!(Vec<(u8, u8, u8)>:
            RustSpec<
                Layout = Unstable,
                Size = size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = <usize as RustSpec>::__Alignment,
                Trap = NonRobust,
                Niche = WithNiche<Unstable>,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = Robust,
            >,
        );
        assert_impl_all!([(u8, u8, u8); 2]:
            RustSpec<
                Layout = Unstable,
                Size = size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = crate::One,
                Trap = Robust,
                Niche = WithoutNiche,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = Robust,
            >,
        );
        assert_impl_all!(Option<(u8, u8, u8)>:
            RustSpec<
                Layout = Unstable,
                Size = size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = crate::One,
                Trap = NonRobust,
                Niche = WithNiche<Unstable>,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = Robust,
            >,
        );
    }

    #[test]
    fn stored_tuple_3_with_niche() {
        assert_impl_all!((u8, StdNonZero<u8>, bool):
            RustSpec<
                Layout = Unstable,
                Size = size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = crate::One,
                Trap = NonRobust,
                Niche = WithNiche<Unstable>,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = Robust,
            >,
        );

        assert_impl_all!(&(u8, StdNonZero<u8>, bool):
            RustSpec<
                Layout = Unstable,
                Size = size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = <usize as RustSpec>::__Alignment,
                Trap = NonRobust,
                Niche = WithNiche<Stable>,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = NonRobust,
            >,
        );
        assert_impl_all!(&mut (u8, StdNonZero<u8>, bool):
            RustSpec<
                Layout = Unstable,
                Size = size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = <usize as RustSpec>::__Alignment,
                Trap = NonRobust,
                Niche = WithNiche<Stable>,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = NonRobust,
            >,
        );
        #[cfg(feature = "alloc")]
        assert_impl_all!(Box<(u8, StdNonZero<u8>, bool)>:
            RustSpec<
                Layout = Unstable,
                Size = size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = <usize as RustSpec>::__Alignment,
                Trap = NonRobust,
                Niche = WithNiche<Stable>,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = NonRobust,
            >,
        );
        #[cfg(feature = "alloc")]
        assert_impl_all!(&[(u8, StdNonZero<u8>, bool)]:
            RustSpec<
                Layout = Unstable,
                Size = size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = <usize as RustSpec>::__Alignment,
                Trap = NonRobust,
                Niche = WithNiche<Unstable>,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = NonRobust,
            >,
        );
        #[cfg(feature = "alloc")]
        assert_impl_all!(&mut [(u8, StdNonZero<u8>, bool)]:
            RustSpec<
                Layout = Unstable,
                Size = size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = <usize as RustSpec>::__Alignment,
                Trap = NonRobust,
                Niche = WithNiche<Unstable>,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = NonRobust,
            >,
        );
        #[cfg(feature = "alloc")]
        assert_impl_all!(Box<[(u8, StdNonZero<u8>, bool)]>:
            RustSpec<
                Layout = Unstable,
                Size = size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = <usize as RustSpec>::__Alignment,
                Trap = NonRobust,
                Niche = WithNiche<Unstable>,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = NonRobust,
            >,
        );
        #[cfg(feature = "alloc")]
        assert_impl_all!(Vec<(u8, StdNonZero<u8>, bool)>:
            RustSpec<
                Layout = Unstable,
                Size = size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = <usize as RustSpec>::__Alignment,
                Trap = NonRobust,
                Niche = WithNiche<Unstable>,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = NonRobust,
            >,
        );
        assert_impl_all!([(u8, StdNonZero<u8>, bool); 2]:
            RustSpec<
                Layout = Unstable,
                Size = size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = crate::One,
                Trap = NonRobust,
                Niche = WithNiche<Unstable>,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = Robust,
            >,
        );
        assert_impl_all!(Option<(u8, StdNonZero<u8>, bool)>:
            RustSpec<
                Layout = Unstable,
                Size = size::Sized<crate::Gt<crate::Zero>>,
                __Alignment = crate::One,
                Trap = NonRobust,
                Niche = WithNiche<Unstable>,
                Mutability = Exclusive<WithoutInterior>,
                __IndirectTrap = Robust,
            >,
        );
    }
}