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}