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}