1macro_rules! impl_fn {
4 ($($nm:ident : $ty:ident),*) => {
6 impl_fn!(@recurse ($($nm : $ty),*) ());
7 };
8
9 (@recurse () ($($nm:ident : $ty:ident),*)) => {
11 impl_fn!(@impl_all ($($nm : $ty),*));
12 };
13 (@recurse ($hd_nm:ident : $hd_ty:ident $(, $tl_nm:ident : $tl_ty:ident)*) ($($nm:ident : $ty:ident),*)) => {
14 impl_fn!(@impl_all ($($nm : $ty),*));
15 impl_fn!(@recurse ($($tl_nm : $tl_ty),*) ($($nm : $ty,)* $hd_nm : $hd_ty));
16 };
17
18 (@impl_all ($($nm:ident : $ty:ident),*)) => {
20 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Rust, "Rust");
22 impl_fn!(@impl_u_and_s ($($nm : $ty),*), C, "C");
23 impl_fn!(@impl_u_and_s ($($nm : $ty),*), CUnwind, "C-unwind");
24 impl_fn!(@impl_u_and_s ($($nm : $ty),*), System, "system");
25 impl_fn!(@impl_u_and_s ($($nm : $ty),*), SystemUnwind, "system-unwind");
26
27 #[cfg(has_abi_cdecl)]
29 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Cdecl, "cdecl");
30 #[cfg(has_abi_cdecl)]
31 impl_fn!(@impl_u_and_s ($($nm : $ty),*), CdeclUnwind, "cdecl-unwind");
32
33 #[cfg(has_abi_stdcall)]
34 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Stdcall, "stdcall");
35 #[cfg(has_abi_stdcall)]
36 impl_fn!(@impl_u_and_s ($($nm : $ty),*), StdcallUnwind, "stdcall-unwind");
37
38 #[cfg(has_abi_fastcall)]
39 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Fastcall, "fastcall");
40 #[cfg(has_abi_fastcall)]
41 impl_fn!(@impl_u_and_s ($($nm : $ty),*), FastcallUnwind, "fastcall-unwind");
42
43 #[cfg(has_abi_thiscall)]
44 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Thiscall, "thiscall");
45 #[cfg(has_abi_thiscall)]
46 impl_fn!(@impl_u_and_s ($($nm : $ty),*), ThiscallUnwind, "thiscall-unwind");
47
48 #[cfg(has_abi_vectorcall)]
49 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Vectorcall, "vectorcall");
50 #[cfg(has_abi_vectorcall)]
51 impl_fn!(@impl_u_and_s ($($nm : $ty),*), VectorcallUnwind, "vectorcall-unwind");
52
53 #[cfg(has_abi_win64)]
54 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Win64, "win64");
55 #[cfg(has_abi_win64)]
56 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Win64Unwind, "win64-unwind");
57
58 #[cfg(has_abi_sysv64)]
59 impl_fn!(@impl_u_and_s ($($nm : $ty),*), SysV64, "sysv64");
60 #[cfg(has_abi_sysv64)]
61 impl_fn!(@impl_u_and_s ($($nm : $ty),*), SysV64Unwind, "sysv64-unwind");
62
63 #[cfg(has_abi_aapcs)]
64 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Aapcs, "aapcs");
65 #[cfg(has_abi_aapcs)]
66 impl_fn!(@impl_u_and_s ($($nm : $ty),*), AapcsUnwind, "aapcs-unwind");
67
68 #[cfg(has_abi_efiapi)]
69 impl_fn!(@impl_u_and_s ($($nm : $ty),*), EfiApi, "efiapi");
70 };
71
72 (@impl_u_and_s ($($nm:ident : $ty:ident),*), $abi_ident:ident, $abi_str:expr) => {
74 impl_fn!(@impl_core ($($nm : $ty),*), extern $abi_str fn($($ty),*) -> Output, true, $abi_ident, $abi_str);
75 impl_fn!(@impl_core ($($nm : $ty),*), unsafe extern $abi_str fn($($ty),*) -> Output, false, $abi_ident, $abi_str);
76 };
77
78 (@impl_core ($($nm:ident : $ty:ident),*), $fn_type:ty, $safety:tt, $abi_ident:ident, $call_conv:expr) => {
80 #[automatically_derived]
81 impl<Output, $($ty),*> $crate::FnPtr for $fn_type {
82 type Args = ($($ty,)*);
83 type Output = Output;
84
85 type Safety = $crate::safety!($safety);
86 type Abi = $crate::abi::$abi_ident;
87
88 const ARITY: ::core::primitive::usize = <<Self::Args as $crate::tuple::Tuple>::Arity as $crate::arity::Arity>::N;
89 const IS_SAFE: ::core::primitive::bool = <Self::Safety as $crate::safety::Safety>::IS_SAFE;
90 const ABI: $crate::AbiValue = <$crate::abi::$abi_ident as $crate::abi::Abi>::VALUE;
91 const IS_EXTERN: ::core::primitive::bool = !matches!(Self::ABI, $crate::AbiValue::Rust);
92
93 fn as_ptr(&self) -> $crate::UntypedFnPtr {
94 *self as $crate::UntypedFnPtr
95 }
96 unsafe fn from_ptr(ptr: $crate::UntypedFnPtr) -> Self {
97 ::core::assert!(!ptr.is_null());
98 unsafe { ::core::mem::transmute::<$crate::UntypedFnPtr, Self>(ptr) }
99 }
100 }
101 impl_fn!(@impl_safe_fn_type ($($nm : $ty),*), $fn_type, $safety);
102
103 #[automatically_derived]
104 impl<Output, $($ty),*> $crate::BuildFn<$crate::safety!($safety), $crate::abi::$abi_ident, Output> for ($($ty,)*) {
105 type F = impl_fn!(@make_unsafe extern $call_conv fn($($ty),*) -> Output, $safety);
106 }
107
108 #[automatically_derived]
110 impl<Output, $($ty),*> $crate::WithSafetyImpl<$crate::safety::Safe> for $fn_type {
111 type F = extern $call_conv fn($($ty),*) -> Output;
112 }
113 #[automatically_derived]
114 impl<Output, $($ty),*> $crate::WithSafetyImpl<$crate::safety::Unsafe> for $fn_type {
115 type F = unsafe extern $call_conv fn($($ty),*) -> Output;
116 }
117
118 #[automatically_derived]
120 impl<Output, $($ty),*> $crate::WithArgsImpl<$fn_type> for $fn_type {
121 type F<Args: $crate::Tuple> = <<<Args::BaseFn as $crate::WithSafety<$crate::safety!($safety)>>::F as $crate::WithAbi<$crate::abi::$abi_ident>>::F as $crate::WithOutput<Output>>::F;
122 }
123
124 #[automatically_derived]
126 impl<Output, $($ty),*> $crate::WithOutputImpl for $fn_type {
127 type F<R> = impl_fn!(@make_unsafe extern $call_conv fn($($ty),*) -> R, $safety);
128 }
129
130 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "Rust");
132 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "C");
133 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "system");
134 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "C-unwind");
135 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "system-unwind");
136
137 #[cfg(has_abi_cdecl)]
138 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "cdecl");
139 #[cfg(has_abi_cdecl)]
140 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "cdecl-unwind");
141
142 #[cfg(has_abi_stdcall)]
143 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "stdcall");
144 #[cfg(has_abi_stdcall)]
145 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "stdcall-unwind");
146
147 #[cfg(has_abi_fastcall)]
148 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "fastcall");
149 #[cfg(has_abi_fastcall)]
150 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "fastcall-unwind");
151
152 #[cfg(has_abi_thiscall)]
153 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "thiscall");
154 #[cfg(has_abi_thiscall)]
155 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "thiscall-unwind");
156
157 #[cfg(has_abi_vectorcall)]
158 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "vectorcall");
159 #[cfg(has_abi_vectorcall)]
160 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "vectorcall-unwind");
161
162 #[cfg(has_abi_win64)]
163 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "win64");
164 #[cfg(has_abi_win64)]
165 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "win64-unwind");
166
167 #[cfg(has_abi_sysv64)]
168 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "sysv64");
169 #[cfg(has_abi_sysv64)]
170 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "sysv64-unwind");
171
172 #[cfg(has_abi_aapcs)]
173 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "aapcs");
174 #[cfg(has_abi_aapcs)]
175 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "aapcs-unwind");
176
177 #[cfg(has_abi_efiapi)]
178 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "efiapi");
179 };
180
181 (@impl_withabi ($($nm:ident : $ty:ident),*), $fn_type:ty, $safety:tt, $abi:tt) => {
182 #[automatically_derived]
183 impl<Output, $($ty),*> $crate::WithAbiImpl<$crate::abi!($abi)> for $fn_type {
184 type F = impl_fn!(@make_unsafe extern $abi fn($($ty),*) -> Output, $safety);
185 }
186 };
187
188 (@make_unsafe $fn_type:ty, true) => { $fn_type };
189 (@make_unsafe extern $abi:literal fn($($args:ty),*) -> $Output:ty, false) => {
190 unsafe extern $abi fn($($args),*) -> $Output
191 };
192
193 (@impl_safe_fn_type ($($nm:ident : $ty:ident),*), $fn_type:ty, true) => {
194 #[automatically_derived]
195 impl<Output, $($ty),*> $crate::SafeFnPtr for $fn_type {
196 fn invoke(&self, ($($nm,)*): Self::Args) -> Self::Output {
197 (*self)($($nm),*)
198 }
199 }
200 };
201 (@impl_safe_fn_type ($($nm:ident : $ty:ident),*), $fn_type:ty, false) => {
202 #[automatically_derived]
203 impl<Output, $($ty),*> $crate::UnsafeFnPtr for $fn_type {
204 unsafe fn invoke(&self, ($($nm,)*): Self::Args) -> Self::Output {
205 unsafe { (*self)($($nm),*) }
206 }
207 }
208 };
209}
210
211#[cfg(not(feature = "max-arity-12"))]
213impl_fn! {
214 __arg_0: A, __arg_1: B, __arg_2: C, __arg_3: D, __arg_4: E, __arg_5: F
215}
216
217#[cfg(feature = "max-arity-12")]
219impl_fn! {
220 __arg_0: A, __arg_1: B, __arg_2: C, __arg_3: D, __arg_4: E, __arg_5: F, __arg_6: G,
221 __arg_7: H, __arg_8: I, __arg_9: J, __arg_10: K, __arg_11: L
222}