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
69 (@impl_u_and_s ($($nm:ident : $ty:ident),*), $abi_ident:ident, $abi_str:expr) => {
71 impl_fn!(@impl_core ($($nm : $ty),*), extern $abi_str fn($($ty),*) -> Ret, true, $abi_ident, $abi_str);
72 impl_fn!(@impl_core ($($nm : $ty),*), unsafe extern $abi_str fn($($ty),*) -> Ret, false, $abi_ident, $abi_str);
73 };
74
75 (@impl_core ($($nm:ident : $ty:ident),*), $fn_type:ty, $safety:tt, $abi_ident:ident, $call_conv:expr) => {
77 #[automatically_derived]
78 impl<Ret, $($ty),*> $crate::FnPtr for $fn_type {
79 type Args = ($($ty,)*);
80 type Output = Ret;
81
82 type ArityMarker = impl_fn!(@arity_marker ($($ty),*));
83 type SafetyMarker = $crate::safety!($safety);
84 type AbiMarker = $crate::marker::$abi_ident;
85
86 const ARITY: ::core::primitive::usize = <Self::ArityMarker as $crate::marker::Arity>::N;
87 const IS_SAFE: ::core::primitive::bool = <Self::SafetyMarker as $crate::marker::Safety>::IS_SAFE;
88 const ABI: $crate::Abi = <$crate::marker::$abi_ident as $crate::marker::Abi>::VALUE;
89 const IS_EXTERN: ::core::primitive::bool = !matches!(Self::ABI, $crate::Abi::Rust);
90
91 fn as_ptr(&self) -> $crate::UntypedFnPtr {
92 *self as $crate::UntypedFnPtr
93 }
94 unsafe fn from_ptr(ptr: $crate::UntypedFnPtr) -> Self {
95 ::core::assert!(!ptr.is_null());
96 unsafe { ::core::mem::transmute::<$crate::UntypedFnPtr, Self>(ptr) }
97 }
98 }
99 impl_fn!(@impl_safe_fn_type ($($nm : $ty),*), $fn_type, $safety);
100
101 #[automatically_derived]
102 impl<Ret: 'static, $($ty: 'static),*> $crate::StaticFnPtr for $fn_type {
103 }
104
105 #[automatically_derived]
107 impl<Ret, $($ty),*> $crate::WithSafety<$crate::marker::Safe> for $fn_type {
108 type F = extern $call_conv fn($($ty),*) -> Ret;
109 }
110 #[automatically_derived]
111 impl<Ret, $($ty),*> $crate::WithSafety<$crate::marker::Unsafe> for $fn_type {
112 type F = unsafe extern $call_conv fn($($ty),*) -> Ret;
113 }
114
115 #[automatically_derived]
117 impl<Ret, $($ty),*> $crate::HasAbi<$crate::marker::$abi_ident> for $fn_type {}
118
119 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "Rust");
121 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "C");
122 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "system");
123 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "C-unwind");
124 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "system-unwind");
125
126 #[cfg(has_abi_cdecl)]
127 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "cdecl");
128 #[cfg(has_abi_cdecl)]
129 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "cdecl-unwind");
130
131 #[cfg(has_abi_stdcall)]
132 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "stdcall");
133 #[cfg(has_abi_stdcall)]
134 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "stdcall-unwind");
135
136 #[cfg(has_abi_fastcall)]
137 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "fastcall");
138 #[cfg(has_abi_fastcall)]
139 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "fastcall-unwind");
140
141 #[cfg(has_abi_thiscall)]
142 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "thiscall");
143 #[cfg(has_abi_thiscall)]
144 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "thiscall-unwind");
145
146 #[cfg(has_abi_vectorcall)]
147 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "vectorcall");
148 #[cfg(has_abi_vectorcall)]
149 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "vectorcall-unwind");
150
151 #[cfg(has_abi_win64)]
152 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "win64");
153 #[cfg(has_abi_win64)]
154 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "win64-unwind");
155
156 #[cfg(has_abi_sysv64)]
157 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "sysv64");
158 #[cfg(has_abi_sysv64)]
159 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "sysv64-unwind");
160
161 #[cfg(has_abi_aapcs)]
162 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "aapcs");
163 #[cfg(has_abi_aapcs)]
164 impl_fn!(@impl_withabi ($($nm : $ty),*), $fn_type, $safety, "aapcs-unwind");
165 };
166
167 (@impl_withabi ($($nm:ident : $ty:ident),*), $fn_type:ty, $safety:tt, $abi:tt) => {
168 #[automatically_derived]
169 impl<Ret, $($ty),*> $crate::WithAbi<$crate::abi!($abi)> for $fn_type {
170 type F = impl_fn!(@make_unsafe extern $abi fn($($ty),*) -> Ret, $safety);
171 }
172 };
173
174 (@arity_marker ()) => { $crate::marker::A0 };
175 (@arity_marker ($a:ty)) => { $crate::marker::A1 };
176 (@arity_marker ($a:ty, $b:ty)) => { $crate::marker::A2 };
177 (@arity_marker ($a:ty, $b:ty, $c:ty)) => { $crate::marker::A3 };
178 (@arity_marker ($a:ty, $b:ty, $c:ty, $d:ty)) => { $crate::marker::A4 };
179 (@arity_marker ($a:ty, $b:ty, $c:ty, $d:ty, $e:ty)) => { $crate::marker::A5 };
180 (@arity_marker ($a:ty, $b:ty, $c:ty, $d:ty, $e:ty, $f:ty)) => { $crate::marker::A6 };
181 (@arity_marker ($a:ty, $b:ty, $c:ty, $d:ty, $e:ty, $f:ty, $g:ty)) => { $crate::marker::A7 };
182 (@arity_marker ($a:ty, $b:ty, $c:ty, $d:ty, $e:ty, $f:ty, $g:ty, $h:ty)) => { $crate::marker::A8 };
183 (@arity_marker ($a:ty, $b:ty, $c:ty, $d:ty, $e:ty, $f:ty, $g:ty, $h:ty, $i:ty)) => { $crate::marker::A9 };
184 (@arity_marker ($a:ty, $b:ty, $c:ty, $d:ty, $e:ty, $f:ty, $g:ty, $h:ty, $i:ty, $j:ty)) => { $crate::marker::A10 };
185 (@arity_marker ($a:ty, $b:ty, $c:ty, $d:ty, $e:ty, $f:ty, $g:ty, $h:ty, $i:ty, $j:ty, $k:ty)) => { $crate::marker::A11 };
186 (@arity_marker ($a:ty, $b:ty, $c:ty, $d:ty, $e:ty, $f:ty, $g:ty, $h:ty, $i:ty, $j:ty, $k:ty, $l:ty)) => { $crate::marker::A12 };
187
188 (@make_unsafe $fn_type:ty, true) => { $fn_type };
189 (@make_unsafe extern $abi:literal fn($($args:ty),*) -> $ret:ty, false) => {
190 unsafe extern $abi fn($($args),*) -> $ret
191 };
192
193 (@impl_safe_fn_type ($($nm:ident : $ty:ident),*), $fn_type:ty, true) => {
194 #[automatically_derived]
195 impl<Ret, $($ty),*> $crate::SafeFnPtr for $fn_type {
196 fn invoke(&self, impl_fn!(@call_args ($($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<Ret, $($ty),*> $crate::UnsafeFnPtr for $fn_type {
204 unsafe fn invoke(&self, impl_fn!(@call_args ($($nm),*)): Self::Args) -> Self::Output {
205 unsafe { (*self)($($nm),*) }
206 }
207 }
208 };
209
210 (@call_args ($single:ident)) => { ($single,) };
211 (@call_args ($($args:ident),*)) => { ($($args),*) };
212}
213
214#[cfg(not(feature = "max-arity-12"))]
216impl_fn! {
217 __arg_0: A, __arg_1: B, __arg_2: C, __arg_3: D, __arg_4: E, __arg_5: F
218}
219
220#[cfg(feature = "max-arity-12")]
222impl_fn! {
223 __arg_0: A, __arg_1: B, __arg_2: C, __arg_3: D, __arg_4: E, __arg_5: F, __arg_6: G,
224 __arg_7: H, __arg_8: I, __arg_9: J, __arg_10: K, __arg_11: L
225}