Skip to main content

rust_spec/
tuple.rs

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