Skip to main content

rust_spec/
tuple.rs

1use core::ops::Add;
2
3use crate::{Max, Maximum, NonOpaque, RustSpec, Sum, Unstable, drop::NeedsDrop, layout::Robust};
4
5macro_rules! impl_tuple_type_spec {
6    (@alignment $ty:ident) => {
7        <$ty as RustSpec>::__Alignment
8    };
9    (@alignment $head:ident, $($tail:ident),+) => {
10        Maximum<<$head as RustSpec>::__Alignment, impl_tuple_type_spec!(@alignment $($tail),+)>
11    };
12    (@kind $axis:ident; $ty:ident) => {
13        <$ty as RustSpec>::$axis
14    };
15    (@kind $axis:ident; $head:ident, $($tail:ident),+) => {
16        Sum<<$head as RustSpec>::$axis, impl_tuple_type_spec!(@kind $axis; $($tail),+)>
17    };
18
19    (@params for $target:ty [$($all:ident),+] [$($params:tt)*]; $ty:ident) => {
20        unsafe impl<$($all),+> RustSpec for $target
21        where
22            $($params)*
23            $ty: RustSpec + ?Sized,
24            Robust: Add<impl_tuple_type_spec!(@kind Trap; $($all),+)>,
25            impl_tuple_type_spec!(@kind Drop; $($all),+): crate::drop::DropKind,
26        {
27            type Layout = Unstable;
28            type Size = impl_tuple_type_spec!(@kind Size; $($all),+);
29            type __Alignment = impl_tuple_type_spec!(@alignment $($all),+);
30            type Trap = Sum<Robust, impl_tuple_type_spec!(@kind Trap; $($all),+)>;
31            type Niche = impl_tuple_type_spec!(@kind Niche; $($all),+);
32            type Drop = NeedsDrop<impl_tuple_type_spec!(@kind Drop; $($all),+)>;
33            type Mutability = impl_tuple_type_spec!(@kind Mutability; $($all),+);
34            type Opacity = NonOpaque;
35            type __IndirectTrap = impl_tuple_type_spec!(@kind __IndirectTrap; $($all),+);
36        }
37    };
38    (@params for $target:ty [$($all:ident),+] [$($params:tt)*]; $head:ident, $($tail:ident),+) => {
39        impl_tuple_type_spec!(
40            @params for $target
41            [$($all),+]
42            [$($params)*
43                $head: RustSpec<
44                    Size: Add<impl_tuple_type_spec!(@kind Size; $($tail),+)>,
45                    __Alignment: Max<
46                        impl_tuple_type_spec!(@alignment $($tail),+),
47                    >,
48                    Trap: Add<impl_tuple_type_spec!(@kind Trap; $($tail),+)>,
49                    Niche: Add<impl_tuple_type_spec!(@kind Niche; $($tail),+)>,
50                    Drop: Add<impl_tuple_type_spec!(@kind Drop; $($tail),+)>,
51                    Mutability: Add<impl_tuple_type_spec!(@kind Mutability; $($tail),+)>,
52                    __IndirectTrap: Add<impl_tuple_type_spec!(@kind __IndirectTrap; $($tail),+)>,
53                >,
54            ]
55            ; $($tail),+
56        );
57    };
58
59    ($(($($ty:ident),+)),+ $(,)?) => { $(
60        impl_tuple_type_spec!(@params for ($($ty,)+) [$($ty),+] []; $($ty),+); )+
61    };
62}
63
64impl_tuple_type_spec! {
65    (A),
66    (A, B),
67    (A, B, C),
68    (A, B, C, D),
69    (A, B, C, D, E),
70    (A, B, C, D, E, F),
71    (A, B, C, D, E, F, G),
72    (A, B, C, D, E, F, G, H),
73    (A, B, C, D, E, F, G, H, I),
74    (A, B, C, D, E, F, G, H, I, J),
75    (A, B, C, D, E, F, G, H, I, J, K),
76    (A, B, C, D, E, F, G, H, I, J, K, L)
77}
78
79#[cfg(test)]
80mod tests {
81    #[cfg(feature = "alloc")]
82    use alloc::{boxed::Box, vec::Vec};
83    use core::num::NonZero as StdNonZero;
84
85    use static_assertions::assert_impl_all;
86
87    use super::*;
88    use crate::{
89        Stable,
90        layout::NonRobust,
91        mutability::{Exclusive, WithoutInterior},
92        niche::{WithNiche, WithoutNiche},
93        size::{self, Zero},
94    };
95
96    #[test]
97    fn tuple_size_family_tracks_zst_fields() {
98        assert_impl_all!(((), ()):
99            RustSpec<
100                Layout = Unstable,
101                Size = size::Sized<Zero>,
102                __Alignment = crate::One,
103                Trap = Robust,
104                Niche = WithoutNiche,
105                Mutability = Exclusive<WithoutInterior>,
106                __IndirectTrap = Robust,
107            >,
108        );
109        assert_impl_all!(((), (), ()):
110            RustSpec<
111                Layout = Unstable,
112                Size = size::Sized<Zero>,
113                __Alignment = crate::One,
114                Trap = Robust,
115                Niche = WithoutNiche,
116                Mutability = Exclusive<WithoutInterior>,
117                __IndirectTrap = Robust,
118            >,
119        );
120    }
121
122    #[test]
123    fn tuple_size_family_tracks_non_zst_fields() {
124        assert_impl_all!(((), u8):
125            RustSpec<
126                Layout = Unstable,
127                Size = crate::size::Sized<crate::Gt<crate::Zero>>,
128                __Alignment = crate::One,
129                Trap = Robust,
130                Niche = WithoutNiche,
131                Mutability = Exclusive<WithoutInterior>,
132                __IndirectTrap = Robust,
133            >,
134        );
135        assert_impl_all!((u8, ()):
136            RustSpec<
137                Layout = Unstable,
138                Size = crate::size::Sized<crate::Gt<crate::Zero>>,
139                __Alignment = crate::One,
140                Trap = Robust,
141                Niche = WithoutNiche,
142                Mutability = Exclusive<WithoutInterior>,
143                __IndirectTrap = Robust,
144            >,
145        );
146        assert_impl_all!(((), u8, ()):
147            RustSpec<
148                Layout = Unstable,
149                Size = crate::size::Sized<crate::Gt<crate::Zero>>,
150                __Alignment = crate::One,
151                Trap = Robust,
152                Niche = WithoutNiche,
153                Mutability = Exclusive<WithoutInterior>,
154                __IndirectTrap = Robust,
155            >,
156        );
157    }
158
159    #[test]
160    fn stored_tuple_3_without_niche() {
161        assert_impl_all!((u8, u8, u8):
162            RustSpec<
163                Layout = Unstable,
164                Size = size::Sized<crate::Gt<crate::Zero>>,
165                __Alignment = crate::One,
166                Trap = Robust,
167                Niche = WithoutNiche,
168                Mutability = Exclusive<WithoutInterior>,
169                __IndirectTrap = Robust,
170            >,
171        );
172
173        assert_impl_all!(&(u8, u8, u8):
174            RustSpec<
175                Layout = Unstable,
176                Size = size::Sized<crate::Gt<crate::Zero>>,
177                __Alignment = <usize as RustSpec>::__Alignment,
178                Trap = NonRobust,
179                Niche = WithNiche<Stable>,
180                Mutability = Exclusive<WithoutInterior>,
181                __IndirectTrap = Robust,
182            >,
183        );
184        assert_impl_all!(&mut (u8, u8, u8):
185            RustSpec<
186                Layout = Unstable,
187                Size = size::Sized<crate::Gt<crate::Zero>>,
188                __Alignment = <usize as RustSpec>::__Alignment,
189                Trap = NonRobust,
190                Niche = WithNiche<Stable>,
191                Mutability = Exclusive<WithoutInterior>,
192                __IndirectTrap = Robust,
193            >,
194        );
195        #[cfg(feature = "alloc")]
196        assert_impl_all!(Box<(u8, u8, u8)>:
197            RustSpec<
198                Layout = Unstable,
199                Size = size::Sized<crate::Gt<crate::Zero>>,
200                __Alignment = <usize as RustSpec>::__Alignment,
201                Trap = NonRobust,
202                Niche = WithNiche<Stable>,
203                Mutability = Exclusive<WithoutInterior>,
204                __IndirectTrap = Robust,
205            >,
206        );
207        #[cfg(feature = "alloc")]
208        assert_impl_all!(&[(u8, u8, u8)]:
209            RustSpec<
210                Layout = Unstable,
211                Size = size::Sized<crate::Gt<crate::Zero>>,
212                __Alignment = <usize as RustSpec>::__Alignment,
213                Trap = NonRobust,
214                Niche = WithNiche<Unstable>,
215                Mutability = Exclusive<WithoutInterior>,
216                __IndirectTrap = Robust,
217            >,
218        );
219        #[cfg(feature = "alloc")]
220        assert_impl_all!(&mut [(u8, u8, u8)]:
221            RustSpec<
222                Layout = Unstable,
223                Size = size::Sized<crate::Gt<crate::Zero>>,
224                __Alignment = <usize as RustSpec>::__Alignment,
225                Trap = NonRobust,
226                Niche = WithNiche<Unstable>,
227                Mutability = Exclusive<WithoutInterior>,
228                __IndirectTrap = Robust,
229            >,
230        );
231        #[cfg(feature = "alloc")]
232        assert_impl_all!(Box<[(u8, u8, u8)]>:
233            RustSpec<
234                Layout = Unstable,
235                Size = size::Sized<crate::Gt<crate::Zero>>,
236                __Alignment = <usize as RustSpec>::__Alignment,
237                Trap = NonRobust,
238                Niche = WithNiche<Unstable>,
239                Mutability = Exclusive<WithoutInterior>,
240                __IndirectTrap = Robust,
241            >,
242        );
243        #[cfg(feature = "alloc")]
244        assert_impl_all!(Vec<(u8, u8, u8)>:
245            RustSpec<
246                Layout = Unstable,
247                Size = size::Sized<crate::Gt<crate::Zero>>,
248                __Alignment = <usize as RustSpec>::__Alignment,
249                Trap = NonRobust,
250                Niche = WithNiche<Unstable>,
251                Mutability = Exclusive<WithoutInterior>,
252                __IndirectTrap = Robust,
253            >,
254        );
255        assert_impl_all!([(u8, u8, u8); 2]:
256            RustSpec<
257                Layout = Unstable,
258                Size = size::Sized<crate::Gt<crate::Zero>>,
259                __Alignment = crate::One,
260                Trap = Robust,
261                Niche = WithoutNiche,
262                Mutability = Exclusive<WithoutInterior>,
263                __IndirectTrap = Robust,
264            >,
265        );
266        assert_impl_all!(Option<(u8, u8, u8)>:
267            RustSpec<
268                Layout = Unstable,
269                Size = size::Sized<crate::Gt<crate::Zero>>,
270                __Alignment = crate::One,
271                Trap = NonRobust,
272                Niche = WithNiche<Unstable>,
273                Mutability = Exclusive<WithoutInterior>,
274                __IndirectTrap = Robust,
275            >,
276        );
277    }
278
279    #[test]
280    fn stored_tuple_3_with_niche() {
281        assert_impl_all!((u8, StdNonZero<u8>, bool):
282            RustSpec<
283                Layout = Unstable,
284                Size = size::Sized<crate::Gt<crate::Zero>>,
285                __Alignment = crate::One,
286                Trap = NonRobust,
287                Niche = WithNiche<Unstable>,
288                Mutability = Exclusive<WithoutInterior>,
289                __IndirectTrap = Robust,
290            >,
291        );
292
293        assert_impl_all!(&(u8, StdNonZero<u8>, bool):
294            RustSpec<
295                Layout = Unstable,
296                Size = size::Sized<crate::Gt<crate::Zero>>,
297                __Alignment = <usize as RustSpec>::__Alignment,
298                Trap = NonRobust,
299                Niche = WithNiche<Stable>,
300                Mutability = Exclusive<WithoutInterior>,
301                __IndirectTrap = NonRobust,
302            >,
303        );
304        assert_impl_all!(&mut (u8, StdNonZero<u8>, bool):
305            RustSpec<
306                Layout = Unstable,
307                Size = size::Sized<crate::Gt<crate::Zero>>,
308                __Alignment = <usize as RustSpec>::__Alignment,
309                Trap = NonRobust,
310                Niche = WithNiche<Stable>,
311                Mutability = Exclusive<WithoutInterior>,
312                __IndirectTrap = NonRobust,
313            >,
314        );
315        #[cfg(feature = "alloc")]
316        assert_impl_all!(Box<(u8, StdNonZero<u8>, bool)>:
317            RustSpec<
318                Layout = Unstable,
319                Size = size::Sized<crate::Gt<crate::Zero>>,
320                __Alignment = <usize as RustSpec>::__Alignment,
321                Trap = NonRobust,
322                Niche = WithNiche<Stable>,
323                Mutability = Exclusive<WithoutInterior>,
324                __IndirectTrap = NonRobust,
325            >,
326        );
327        #[cfg(feature = "alloc")]
328        assert_impl_all!(&[(u8, StdNonZero<u8>, bool)]:
329            RustSpec<
330                Layout = Unstable,
331                Size = size::Sized<crate::Gt<crate::Zero>>,
332                __Alignment = <usize as RustSpec>::__Alignment,
333                Trap = NonRobust,
334                Niche = WithNiche<Unstable>,
335                Mutability = Exclusive<WithoutInterior>,
336                __IndirectTrap = NonRobust,
337            >,
338        );
339        #[cfg(feature = "alloc")]
340        assert_impl_all!(&mut [(u8, StdNonZero<u8>, bool)]:
341            RustSpec<
342                Layout = Unstable,
343                Size = size::Sized<crate::Gt<crate::Zero>>,
344                __Alignment = <usize as RustSpec>::__Alignment,
345                Trap = NonRobust,
346                Niche = WithNiche<Unstable>,
347                Mutability = Exclusive<WithoutInterior>,
348                __IndirectTrap = NonRobust,
349            >,
350        );
351        #[cfg(feature = "alloc")]
352        assert_impl_all!(Box<[(u8, StdNonZero<u8>, bool)]>:
353            RustSpec<
354                Layout = Unstable,
355                Size = size::Sized<crate::Gt<crate::Zero>>,
356                __Alignment = <usize as RustSpec>::__Alignment,
357                Trap = NonRobust,
358                Niche = WithNiche<Unstable>,
359                Mutability = Exclusive<WithoutInterior>,
360                __IndirectTrap = NonRobust,
361            >,
362        );
363        #[cfg(feature = "alloc")]
364        assert_impl_all!(Vec<(u8, StdNonZero<u8>, bool)>:
365            RustSpec<
366                Layout = Unstable,
367                Size = size::Sized<crate::Gt<crate::Zero>>,
368                __Alignment = <usize as RustSpec>::__Alignment,
369                Trap = NonRobust,
370                Niche = WithNiche<Unstable>,
371                Mutability = Exclusive<WithoutInterior>,
372                __IndirectTrap = NonRobust,
373            >,
374        );
375        assert_impl_all!([(u8, StdNonZero<u8>, bool); 2]:
376            RustSpec<
377                Layout = Unstable,
378                Size = size::Sized<crate::Gt<crate::Zero>>,
379                __Alignment = crate::One,
380                Trap = NonRobust,
381                Niche = WithNiche<Unstable>,
382                Mutability = Exclusive<WithoutInterior>,
383                __IndirectTrap = Robust,
384            >,
385        );
386        assert_impl_all!(Option<(u8, StdNonZero<u8>, bool)>:
387            RustSpec<
388                Layout = Unstable,
389                Size = size::Sized<crate::Gt<crate::Zero>>,
390                __Alignment = crate::One,
391                Trap = NonRobust,
392                Niche = WithNiche<Unstable>,
393                Mutability = Exclusive<WithoutInterior>,
394                __IndirectTrap = Robust,
395            >,
396        );
397    }
398}