const_type_layout/
inhabited.rs

1//! Helper module to compute whether a combination of types implementing
2//! [`crate::TypeLayout`] are [inhabited] or [uninhabited].
3//!
4//! [inhabited]: https://doc.rust-lang.org/reference/glossary.html#inhabited
5//! [uninhabited]: https://doc.rust-lang.org/reference/glossary.html#uninhabited
6
7#![allow(clippy::undocumented_unsafe_blocks)]
8
9/// Marker type used to specify that a type implementing
10/// [`crate::TypeLayout::Inhabited`] is
11/// [inhabited](https://doc.rust-lang.org/reference/glossary.html#inhabited).
12pub struct Inhabited;
13
14unsafe impl crate::TypeLayout for Inhabited {
15    type Inhabited = Self;
16
17    const TYPE_LAYOUT: crate::TypeLayoutInfo<'static> = crate::TypeLayoutInfo {
18        name: ::core::any::type_name::<Self>(),
19        size: ::core::mem::size_of::<Self>(),
20        alignment: ::core::mem::align_of::<Self>(),
21        structure: crate::TypeStructure::Struct {
22            repr: "",
23            fields: &[],
24        },
25    };
26}
27
28unsafe impl crate::typeset::ComputeTypeSet for Inhabited {
29    type Output<T: crate::typeset::ExpandTypeSet> = crate::typeset::tset![.. @ T];
30}
31
32#[allow(clippy::empty_enum)]
33/// Marker type used to specify that a type implementing
34/// [`crate::TypeLayout::Inhabited`] is
35/// [uninhabited](https://doc.rust-lang.org/reference/glossary.html#uninhabited).
36pub enum Uninhabited {}
37
38unsafe impl crate::TypeLayout for Uninhabited {
39    type Inhabited = Self;
40
41    const TYPE_LAYOUT: crate::TypeLayoutInfo<'static> = crate::TypeLayoutInfo {
42        name: ::core::any::type_name::<Self>(),
43        size: ::core::mem::size_of::<Self>(),
44        alignment: ::core::mem::align_of::<Self>(),
45        structure: crate::TypeStructure::Enum {
46            repr: "",
47            variants: &[],
48        },
49    };
50}
51
52unsafe impl crate::typeset::ComputeTypeSet for Uninhabited {
53    type Output<T: crate::typeset::ExpandTypeSet> = crate::typeset::tset![.. @ T];
54}
55
56#[allow(clippy::module_name_repetitions)]
57#[doc(hidden)]
58pub trait ComputeInhabited: sealed::ComputeInhabited {
59    type Output: OutputMaybeInhabited;
60}
61
62#[allow(clippy::module_name_repetitions)]
63#[doc(hidden)]
64pub trait OutputMaybeInhabited:
65    ComputeInhabited + crate::TypeGraphLayout + sealed::OutputMaybeInhabited
66{
67}
68
69mod sealed {
70    pub trait ComputeInhabited {}
71    pub trait OutputMaybeInhabited {}
72}
73
74impl sealed::ComputeInhabited for Inhabited {}
75impl ComputeInhabited for Inhabited {
76    type Output = Self;
77}
78impl sealed::OutputMaybeInhabited for Inhabited {}
79impl OutputMaybeInhabited for Inhabited {}
80
81impl sealed::ComputeInhabited for Uninhabited {}
82impl ComputeInhabited for Uninhabited {
83    type Output = Self;
84}
85impl sealed::OutputMaybeInhabited for Uninhabited {}
86impl OutputMaybeInhabited for Uninhabited {}
87
88mod logical {
89    use super::{sealed, ComputeInhabited, Inhabited, Uninhabited};
90
91    pub struct And<L: ComputeInhabited, R: ComputeInhabited> {
92        _left: L,
93        _right: R,
94    }
95
96    impl<L: ComputeInhabited, R: ComputeInhabited> sealed::ComputeInhabited for And<L, R> {}
97    impl<L: ComputeInhabited, R: ComputeInhabited> ComputeInhabited for And<L, R> {
98        default type Output = Uninhabited;
99    }
100
101    impl<L: ComputeInhabited<Output = Inhabited>, R: ComputeInhabited<Output = Inhabited>>
102        ComputeInhabited for And<L, R>
103    {
104        type Output = Inhabited;
105    }
106
107    pub struct Or<L: ComputeInhabited, R: ComputeInhabited> {
108        _left: L,
109        _right: R,
110    }
111
112    impl<L: ComputeInhabited, R: ComputeInhabited> sealed::ComputeInhabited for Or<L, R> {}
113    impl<L: ComputeInhabited, R: ComputeInhabited> ComputeInhabited for Or<L, R> {
114        default type Output = Inhabited;
115    }
116
117    impl<L: ComputeInhabited<Output = Uninhabited>, R: ComputeInhabited<Output = Uninhabited>>
118        ComputeInhabited for Or<L, R>
119    {
120        type Output = Uninhabited;
121    }
122}
123
124/// Helper macro to compute whether all of a list of types, all implementing
125/// [`crate::TypeLayout`], e.g. `[T, U, V]`, are [inhabited].
126///
127/// For instance, a struct is inhabited iff all of its fields are inhabited.
128/// The empty list of types is inhabited. This macro resolves into either
129/// [`Inhabited`] or [`Uninhabited`].
130///
131/// [inhabited]: https://doc.rust-lang.org/reference/glossary.html#inhabited
132pub macro all {
133    () => { Inhabited },
134    ($L:ty $(, $R:ty)*) => {
135        <logical::And<<$L as $crate::TypeLayout>::Inhabited, all![$($R),*]> as ComputeInhabited>::Output
136    },
137}
138
139/// Helper macro to compute whether any of a list of types, all implementing
140/// [`crate::TypeLayout`], e.g. `[T, U, V]`, is [inhabited].
141///
142/// For instance, an enum is inhabited iff any of its variants is inhabited.
143/// The empty list of types is [uninhabited]. This macro resolves into either
144/// [`Inhabited`] or [`Uninhabited`].
145///
146/// [inhabited]: https://doc.rust-lang.org/reference/glossary.html#inhabited
147/// [uninhabited]: https://doc.rust-lang.org/reference/glossary.html#uninhabited
148pub macro any {
149    () => { Uninhabited },
150    ($L:ty $(, $R:ty)*) => {
151        <logical::Or<<$L as $crate::TypeLayout>::Inhabited, any![$($R),*]> as ComputeInhabited>::Output
152    },
153}