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}