1use core::{cmp::Ordering, ops::Add};
4
5use crate::{
6 NonOpaque, RustSpec, Stable, Sum, Unstable, Zero,
7 drop::{NeedsDrop, NoDrop},
8 layout::{NonRobust, Robust},
9 mutability::{Exclusive, WithoutInterior},
10 niche::{WithNiche, WithoutNiche},
11 size::{self, MetaSized, SliceLike},
12};
13
14macro_rules! primitive_derive {
15 ( $primitive:ty => $alignment:ty ) => {
16 unsafe impl RustSpec for $primitive {
17 type Layout = Stable;
18 type Size = size::Sized<crate::Gt<Zero>>;
19 type __Alignment = $alignment;
20 type Trap = Robust;
21 type Niche = WithoutNiche;
22 type Drop = NoDrop;
23 type Mutability = Exclusive<WithoutInterior>;
24 type Opacity = NonOpaque;
25 type __IndirectTrap = Robust;
26 }
27 };
28}
29
30macro_rules! impl_nonempty_array {
31 ($($n:literal),* $(,)?) => { $(
32 unsafe impl<R: RustSpec> RustSpec for [R; $n]
33 where
34 WithoutNiche: Add<R::Niche>,
35 R::Drop: crate::drop::DropKind,
36 {
37 type Layout = R::Layout;
38 type Size = R::Size;
39 type __Alignment = R::__Alignment;
40 type Trap = R::Trap;
41 type Niche = Sum<WithoutNiche, R::Niche>;
42 type Drop = NeedsDrop<R::Drop>;
43 type Mutability = R::Mutability;
44 type Opacity = NonOpaque;
45 type __IndirectTrap = R::__IndirectTrap;
46 })*
47 };
48}
49
50macro_rules! impl_fn_types {
51 ( $( ( $( $arg:ident ),* ) ),* $(,)? ) => {
52 $(
53 impl_fn_types!(@rust fn($($arg),*) -> R; $($arg),*);
54 impl_fn_types!(@rust unsafe fn($($arg),*) -> R; $($arg),*);
55 impl_fn_types!(@abi "C"; $($arg),*);
56 impl_fn_types!(@abi "C-unwind"; $($arg),*);
57 impl_fn_types!(@abi "system"; $($arg),*);
58 impl_fn_types!(@abi "system-unwind"; $($arg),*);
59 #[cfg(target_arch = "x86")]
60 impl_fn_types!(@abi "cdecl"; $($arg),*);
61 #[cfg(target_arch = "x86")]
62 impl_fn_types!(@abi "cdecl-unwind"; $($arg),*);
63 #[cfg(target_arch = "x86")]
64 impl_fn_types!(@abi "stdcall"; $($arg),*);
65 #[cfg(target_arch = "x86")]
66 impl_fn_types!(@abi "stdcall-unwind"; $($arg),*);
67 #[cfg(target_arch = "x86")]
68 impl_fn_types!(@abi "fastcall"; $($arg),*);
69 #[cfg(target_arch = "x86")]
70 impl_fn_types!(@abi "fastcall-unwind"; $($arg),*);
71 #[cfg(target_arch = "x86")]
72 impl_fn_types!(@abi "thiscall"; $($arg),*);
73 #[cfg(target_arch = "x86")]
74 impl_fn_types!(@abi "thiscall-unwind"; $($arg),*);
75 #[cfg(target_arch = "x86_64")]
76 impl_fn_types!(@abi "sysv64"; $($arg),*);
77 #[cfg(target_arch = "x86_64")]
78 impl_fn_types!(@abi "sysv64-unwind"; $($arg),*);
79 #[cfg(target_arch = "x86_64")]
80 impl_fn_types!(@abi "win64"; $($arg),*);
81 #[cfg(target_arch = "x86_64")]
82 impl_fn_types!(@abi "win64-unwind"; $($arg),*);
83 #[cfg(target_arch = "arm")]
84 impl_fn_types!(@abi "aapcs"; $($arg),*);
85 #[cfg(target_arch = "arm")]
86 impl_fn_types!(@abi "aapcs-unwind"; $($arg),*);
87 #[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "arm", target_arch = "aarch64"))]
88 impl_fn_types!(@abi "efiapi"; $($arg),*);
89 )*
90 };
91 (@abi $abi:literal; $($arg:ident),*) => {
92 impl_fn_types!(@c extern $abi fn($($arg),*) -> R; [] [<R as RustSpec>::Layout]; $($arg),*);
93 impl_fn_types!(@c unsafe extern $abi fn($($arg),*) -> R; [] [<R as RustSpec>::Layout]; $($arg),*);
94 const _: () = {
95 assert!(core::mem::align_of::<extern $abi fn()>() > 1);
96 assert!(core::mem::align_of::<unsafe extern $abi fn()>() > 1);
97 };
98 };
99 (@rust $fn_type:ty; $($arg:ident),*) => {
100 impl_fn_types!(@impl $fn_type; [$($arg,)* R] [Unstable]);
101 };
102 (@c $fn_type:ty; [$($params:tt)*] [$layout:ty]; $next:ident $(, $rest:ident)*) => {
103 impl_fn_types!(@c $fn_type;
104 [$($params)* $next: RustSpec<Layout: Add<$layout>>,]
105 [Sum<<$next as RustSpec>::Layout, $layout>]; $($rest),*);
106 };
107 (@c $fn_type:ty; [$($params:tt)*] [$layout:ty];) => {
108 impl_fn_types!(@impl $fn_type; [$($params)* R: RustSpec] [$layout]);
109 };
110 (@impl $fn_type:ty; [$($params:tt)*] [$layout:ty]) => {
111 unsafe impl<$($params)*> RustSpec for $fn_type {
112 type Layout = $layout;
113 type Size = size::Sized<crate::Gt<Zero>>;
114 type __Alignment = <usize as RustSpec>::__Alignment;
115 type Trap = NonRobust;
116 type Niche = WithNiche<Stable>;
117 type Drop = NoDrop;
118 type Mutability = Exclusive<WithoutInterior>;
119 type Opacity = NonOpaque;
120 type __IndirectTrap = Robust;
121 }
122 };
123}
124
125macro_rules! fieldless_enum_derive {
126 ( $src:ty => $alignment:ty ) => {
127 unsafe impl RustSpec for $src {
128 type Layout = Stable;
129 type Size = size::Sized<crate::Gt<Zero>>;
130 type __Alignment = $alignment;
131 type Trap = NonRobust;
132 type Niche = WithNiche<Unstable>;
133 type Drop = NoDrop;
134 type Mutability = Exclusive<WithoutInterior>;
135 type Opacity = NonOpaque;
136 type __IndirectTrap = Robust;
137 }
138 };
139}
140
141primitive_derive! { u8 => crate::One }
142primitive_derive! { i8 => crate::One }
143primitive_derive! { u16 => crate::Gt<crate::One> }
144primitive_derive! { i16 => crate::Gt<crate::One> }
145primitive_derive! { u32 => crate::Gt<crate::One> }
146primitive_derive! { i32 => crate::Gt<crate::One> }
147primitive_derive! { u64 => crate::Gt<crate::One> }
148primitive_derive! { i64 => crate::Gt<crate::One> }
149primitive_derive! { u128 => crate::Gt<crate::One> }
150primitive_derive! { i128 => crate::Gt<crate::One> }
151primitive_derive! { f32 => crate::Gt<crate::One> }
152primitive_derive! { f64 => crate::Gt<crate::One> }
153
154#[cfg(target_pointer_width = "16")]
155primitive_derive! { usize => crate::Gt<crate::One> }
156#[cfg(target_pointer_width = "32")]
157primitive_derive! { usize => crate::Gt<crate::One> }
158#[cfg(target_pointer_width = "64")]
159primitive_derive! { usize => crate::Gt<crate::One> }
160
161primitive_derive! { isize => <usize as RustSpec>::__Alignment }
162
163unsafe impl<R: RustSpec> RustSpec for [R]
164where
165 R::Drop: crate::drop::DropKind,
166{
167 type Layout = R::Layout;
168 type Size = MetaSized<SliceLike>;
169 type __Alignment = R::__Alignment;
170 type Trap = R::Trap;
171 type Niche = WithoutNiche;
174 type Drop = NeedsDrop<R::Drop>;
175 type Mutability = R::Mutability;
176 type Opacity = NonOpaque;
177 type __IndirectTrap = R::__IndirectTrap;
178}
179
180unsafe impl<R: RustSpec> RustSpec for [R; 0] {
181 type Layout = R::Layout;
182 type Size = size::Sized<Zero>;
183 type __Alignment = R::__Alignment;
184 type Trap = Robust;
185 type Niche = WithoutNiche;
186 type Drop = NoDrop;
187 type Mutability = Exclusive<WithoutInterior>;
188 type Opacity = NonOpaque;
189 type __IndirectTrap = Robust;
190}
191
192impl_nonempty_array!(
193 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
194 27, 28, 29, 30, 31, 32
195);
196
197impl_fn_types! {
198 (),
199 (A),
200 (A, B),
201 (A, B, C),
202 (A, B, C, D),
203 (A, B, C, D, E),
204 (A, B, C, D, E, F),
205 (A, B, C, D, E, F, G),
206 (A, B, C, D, E, F, G, H),
207 (A, B, C, D, E, F, G, H, I),
208 (A, B, C, D, E, F, G, H, I, J),
209 (A, B, C, D, E, F, G, H, I, J, K),
210 (A, B, C, D, E, F, G, H, I, J, K, L),
211}
212
213const _: () = {
216 assert!(core::mem::align_of::<fn()>() > 1);
217 assert!(core::mem::align_of::<unsafe fn()>() > 1);
218};
219
220fieldless_enum_derive! { char => crate::Gt<crate::One> }
221fieldless_enum_derive! { bool => crate::One }
222fieldless_enum_derive! { Ordering => crate::One }
223
224#[cfg(test)]
225mod tests {
226 #[cfg(feature = "alloc")]
227 use alloc::{boxed::Box, vec::Vec};
228 use static_assertions::assert_impl_all;
229
230 use super::*;
231 use crate::{
232 Unstable,
233 layout::{NonRobust, Robust},
234 niche::WithNiche,
235 };
236
237 #[test]
238 fn function_pointer_classification() {
239 type RustFn = fn();
240 type CFn12 = extern "C" fn(u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8);
241
242 assert_impl_all!(RustFn: RustSpec<Layout = Unstable, Niche = WithNiche<Stable>>);
243 assert_impl_all!(unsafe fn(u8) -> u16: RustSpec<Layout = Unstable>);
244 assert_impl_all!(extern "Rust" fn(u8) -> u16: RustSpec<Layout = Unstable>);
245 assert_impl_all!(extern "C" fn(u8) -> u16: RustSpec<Layout = Stable>);
246 assert_impl_all!(unsafe extern "C" fn(u8) -> u16: RustSpec<Layout = Stable>);
247 assert_impl_all!(extern "C-unwind" fn(u8) -> u16: RustSpec<Layout = Stable>);
248 assert_impl_all!(extern "system" fn(u8) -> u16: RustSpec<Layout = Stable>);
249 assert_impl_all!(extern "system-unwind" fn(u8) -> u16: RustSpec<Layout = Stable>);
250 #[cfg(target_arch = "x86_64")]
251 assert_impl_all!(extern "sysv64" fn(u8) -> u16: RustSpec<Layout = Stable>);
252 #[cfg(target_arch = "x86_64")]
253 assert_impl_all!(extern "win64" fn(u8) -> u16: RustSpec<Layout = Stable>);
254 assert_impl_all!(extern "C" fn((u8,)) -> u16: RustSpec<Layout = Unstable>);
255 assert_impl_all!(extern "C" fn(u8) -> (u16,): RustSpec<Layout = Unstable>);
256 assert_impl_all!(CFn12: RustSpec<Layout = Stable>);
257 }
258
259 #[test]
260 fn function_pointer_option_has_pointer_size() {
261 macro_rules! assert_option_pointer_size {
262 ($pointer:ty) => {
263 assert_eq!(
264 core::mem::size_of::<Option<$pointer>>(),
265 core::mem::size_of::<$pointer>()
266 );
267 };
268 }
269
270 fn named() {}
271 let _: fn() = named;
272
273 assert_option_pointer_size!(fn());
274 assert_option_pointer_size!(unsafe fn(u8) -> u16);
275 assert_option_pointer_size!(extern "C" fn(u8) -> u16);
276 assert_option_pointer_size!(unsafe extern "C-unwind" fn(u8) -> u16);
277 assert_option_pointer_size!(extern "system" fn());
278 }
279
280 #[test]
281 fn robust_u8() {
282 assert_impl_all!(u8:
283 RustSpec<
284 Layout = Stable,
285 Size = size::Sized<crate::Gt<Zero>>,
286 __Alignment = crate::One,
287 Trap = Robust,
288 Niche = WithoutNiche,
289 Mutability = Exclusive<WithoutInterior>,
290 __IndirectTrap = Robust,
291 >,
292 );
293 assert_impl_all!(&u8:
294 RustSpec<
295 Layout = Stable,
296 Size = size::Sized<crate::Gt<Zero>>,
297 __Alignment = <usize as RustSpec>::__Alignment,
298 Trap = NonRobust,
299 Niche = WithNiche<crate::Stable>,
300 Mutability = Exclusive<WithoutInterior>,
301 __IndirectTrap = Robust,
302 >,
303 );
304 assert_impl_all!(&mut u8:
305 RustSpec<
306 Layout = Stable,
307 Size = size::Sized<crate::Gt<Zero>>,
308 __Alignment = <usize as RustSpec>::__Alignment,
309 Trap = NonRobust,
310 Niche = WithNiche<crate::Stable>,
311 Mutability = Exclusive<WithoutInterior>,
312 __IndirectTrap = Robust,
313 >,
314 );
315 #[cfg(feature = "alloc")]
316 assert_impl_all!(Box<u8>:
317 RustSpec<
318 Layout = Stable,
319 Size = size::Sized<crate::Gt<Zero>>,
320 __Alignment = <usize as RustSpec>::__Alignment,
321 Trap = NonRobust,
322 Niche = WithNiche<crate::Stable>,
323 Mutability = Exclusive<WithoutInterior>,
324 __IndirectTrap = Robust,
325 >,
326 );
327 assert_impl_all!(&[u8]:
328 RustSpec<
329 Layout = Unstable,
330 Size = size::Sized<crate::Gt<Zero>>,
331 __Alignment = <usize as RustSpec>::__Alignment,
332 Trap = NonRobust,
333 Niche = WithNiche<crate::Unstable>,
334 Mutability = Exclusive<WithoutInterior>,
335 __IndirectTrap = Robust,
336 >,
337 );
338 assert_impl_all!(&mut [u8]:
339 RustSpec<
340 Layout = Unstable,
341 Size = size::Sized<crate::Gt<Zero>>,
342 __Alignment = <usize as RustSpec>::__Alignment,
343 Trap = NonRobust,
344 Niche = WithNiche<crate::Unstable>,
345 Mutability = Exclusive<WithoutInterior>,
346 __IndirectTrap = Robust,
347 >,
348 );
349 #[cfg(feature = "alloc")]
350 assert_impl_all!(Box<[u8]>:
351 RustSpec<
352 Layout = Unstable,
353 Size = size::Sized<crate::Gt<Zero>>,
354 __Alignment = <usize as RustSpec>::__Alignment,
355 Trap = NonRobust,
356 Niche = WithNiche<crate::Unstable>,
357 Mutability = Exclusive<WithoutInterior>,
358 __IndirectTrap = Robust,
359 >,
360 );
361 #[cfg(feature = "alloc")]
362 assert_impl_all!(Vec<u8>:
363 RustSpec<
364 Layout = Unstable,
365 Size = size::Sized<crate::Gt<Zero>>,
366 __Alignment = <usize as RustSpec>::__Alignment,
367 Trap = NonRobust,
368 Niche = WithNiche<crate::Unstable>,
369 Mutability = Exclusive<WithoutInterior>,
370 __IndirectTrap = Robust,
371 >,
372 );
373 assert_impl_all!([u8; 2]:
374 RustSpec<
375 Layout = Stable,
376 Size = size::Sized<crate::Gt<Zero>>,
377 __Alignment = crate::One,
378 Trap = Robust,
379 Niche = WithoutNiche,
380 Mutability = Exclusive<WithoutInterior>,
381 __IndirectTrap = Robust,
382 >,
383 );
384 assert_impl_all!(Option<u8>:
385 RustSpec<
386 Layout = Unstable,
387 Size = size::Sized<crate::Gt<Zero>>,
388 __Alignment = crate::One,
389 Trap = NonRobust,
390 Niche = WithNiche<crate::Unstable>,
391 Mutability = Exclusive<WithoutInterior>,
392 __IndirectTrap = Robust,
393 >,
394 );
395 }
396}