Skip to main content

rust_spec/
tuple.rs

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