Skip to content

Commit ca3beb0

Browse files
committed
Varous improvements
Add functions to FnPtr to transmute instances Make WithAbi work on stable Deduplicate impl_fn macro
1 parent 5a138b2 commit ca3beb0

4 files changed

Lines changed: 217 additions & 153 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ All macros rely on type-level traits [`WithAbi`](https://docs.rs/fn-ptr/latest/f
8787
use fn_ptr::{FnPtr, WithAbi, WithSafety, Abi};
8888

8989
type F = extern "C" fn(i32);
90-
type G = <F as WithAbi<{Abi::Sysv64}, F>>::F;
91-
type U = <F as WithSafety<{false}, F>>::F;
90+
type G = <F as WithAbi<{Abi::Sysv64}>>::F;
91+
type U = <F as WithSafety<{false}>>::F;
9292
```
9393

9494
## License

src/abi.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,15 @@ pub const fn parse_or_fail(conv: &'static str) -> Abi {
167167
concat_panic!("invalid or unknown abi", conv)
168168
}
169169
}
170+
171+
#[cfg(feature = "nightly")]
172+
pub(crate) type AbiKey = Abi;
173+
#[cfg(not(feature = "nightly"))]
174+
pub(crate) type AbiKey = u8;
175+
176+
#[must_use]
177+
/// Returns the value used to designate the given ABI in const generics.
178+
/// For stable or beta builds this returns an [`u8`], while on nightly the [`Abi`] instance is returned.
179+
pub const fn key(abi: Abi) -> AbiKey {
180+
abi as _
181+
}

src/impl.rs

Lines changed: 76 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
// NOTE: ABI target cfgs are provided by the build script as `has_abi_<name>`.
22

3-
macro_rules! cfg_all {
4-
($meta:meta { $($items:item)* }) => {
5-
$(#[cfg($meta)] $items)*
6-
};
7-
}
8-
93
macro_rules! impl_fn {
104
(@recurse () ($($nm:ident : $ty:ident),*)) => {
115
impl_fn!(@impl_all ($($nm : $ty),*));
@@ -38,14 +32,14 @@ macro_rules! impl_fn {
3832
impl_fn!(@impl_core ($($nm : $ty),*), unsafe extern $abi_str fn($($ty),*) -> Ret, false, $abi_ident, $abi_str);
3933
};
4034

41-
(@impl_core ($($nm:ident : $ty:ident),*), $fn_type:ty, true, $abi_ident:ident, $call_conv:expr) => {
35+
(@impl_core ($($nm:ident : $ty:ident),*), $fn_type:ty, $safety:tt, $abi_ident:ident, $call_conv:expr) => {
4236
#[automatically_derived]
4337
impl<Ret: 'static, $($ty: 'static),*> $crate::FnPtr for $fn_type {
4438
type Args = ($($ty,)*);
4539
type Output = Ret;
4640

4741
const ARITY: ::core::primitive::usize = impl_fn!(@count ($($ty)*));
48-
const IS_SAFE: ::core::primitive::bool = true;
42+
const IS_SAFE: ::core::primitive::bool = $safety;
4943
const IS_EXTERN: ::core::primitive::bool = !matches!($crate::Abi::$abi_ident, $crate::Abi::Rust);
5044
const ABI: $crate::Abi = $crate::Abi::$abi_ident;
5145

@@ -54,97 +48,68 @@ macro_rules! impl_fn {
5448
}
5549
unsafe fn from_ptr(ptr: $crate::UntypedFnPtr) -> Self {
5650
::core::assert!(!ptr.is_null());
57-
unsafe { ::core::mem::transmute(ptr) }
58-
}
59-
}
60-
#[automatically_derived]
61-
impl<Ret: 'static, $($ty: 'static),*> $crate::SafeFnPtr for $fn_type {
62-
fn invoke(&self, impl_fn!(@call_args ($($nm),*)): Self::Args) -> Self::Output {
63-
(*self)($($nm),*)
51+
unsafe { ::core::mem::transmute::<$crate::UntypedFnPtr, Self>(ptr) }
6452
}
6553
}
54+
impl_fn!(@impl_safe_fn_type ($($nm : $ty),*), $fn_type, $safety);
6655

6756
// WithSafety
6857
#[automatically_derived]
69-
impl<Ret: 'static, $($ty: 'static),*> $crate::WithSafety<{true}, $fn_type> for $fn_type { type F = $fn_type; }
58+
impl<Ret: 'static, $($ty: 'static),*> $crate::WithSafety<{true}> for $fn_type {
59+
type F = extern $call_conv fn($($ty),*) -> Ret;
60+
}
7061
#[automatically_derived]
71-
impl<Ret: 'static, $($ty: 'static),*> $crate::WithSafety<{false}, $fn_type> for $fn_type { type F = unsafe extern $call_conv fn($($ty),*) -> Ret; }
72-
73-
cfg_all!(feature = "nightly" {
74-
// HasAbi
75-
#[automatically_derived]
76-
impl<Ret: 'static, $($ty: 'static),*> $crate::HasAbi<{$crate::Abi::$abi_ident}> for $fn_type {}
77-
78-
// WithAbi
79-
#[automatically_derived] impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Rust}, $fn_type> for $fn_type { type F = extern "Rust" fn($($ty),*) -> Ret; }
80-
#[automatically_derived] impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::C}, $fn_type> for $fn_type { type F = extern "C" fn($($ty),*) -> Ret; }
81-
#[automatically_derived] impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::System}, $fn_type> for $fn_type { type F = extern "system" fn($($ty),*) -> Ret; }
82-
#[cfg(has_abi_cdecl)]
83-
#[automatically_derived] impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Cdecl}, $fn_type> for $fn_type { type F = extern "cdecl" fn($($ty),*) -> Ret; }
84-
#[cfg(has_abi_stdcall)]
85-
#[automatically_derived] impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Stdcall}, $fn_type> for $fn_type { type F = extern "stdcall" fn($($ty),*) -> Ret; }
86-
#[cfg(has_abi_fastcall)]
87-
#[automatically_derived] impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Fastcall}, $fn_type> for $fn_type { type F = extern "fastcall" fn($($ty),*) -> Ret; }
88-
#[cfg(has_abi_win64)]
89-
#[automatically_derived] impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Win64}, $fn_type> for $fn_type { type F = extern "win64" fn($($ty),*) -> Ret; }
90-
#[cfg(has_abi_sysv64)]
91-
#[automatically_derived] impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Sysv64}, $fn_type> for $fn_type { type F = extern "sysv64" fn($($ty),*) -> Ret; }
92-
#[cfg(has_abi_aapcs)]
93-
#[automatically_derived] impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Aapcs}, $fn_type> for $fn_type { type F = extern "aapcs" fn($($ty),*) -> Ret; }
94-
});
95-
};
62+
impl<Ret: 'static, $($ty: 'static),*> $crate::WithSafety<{false}> for $fn_type {
63+
type F = unsafe extern $call_conv fn($($ty),*) -> Ret;
64+
}
9665

97-
(@impl_core ($($nm:ident : $ty:ident),*), $fn_type:ty, false, $abi_ident:ident, $call_conv:expr) => {
66+
// HasAbi
9867
#[automatically_derived]
99-
impl<Ret: 'static, $($ty: 'static),*> $crate::FnPtr for $fn_type {
100-
type Args = ($($ty,)*);
101-
type Output = Ret;
68+
impl<Ret: 'static, $($ty: 'static),*> $crate::HasAbi<{$crate::abi::key($crate::Abi::$abi_ident)}> for $fn_type {}
10269

103-
const ARITY: ::core::primitive::usize = impl_fn!(@count ($($ty)*));
104-
const IS_SAFE: ::core::primitive::bool = false;
105-
const IS_EXTERN: ::core::primitive::bool = !matches!($crate::Abi::$abi_ident, $crate::Abi::Rust);
106-
const ABI: $crate::Abi = $crate::Abi::$abi_ident;
107-
108-
fn as_ptr(&self) -> $crate::UntypedFnPtr {
109-
*self as $crate::UntypedFnPtr
110-
}
111-
unsafe fn from_ptr(ptr: $crate::UntypedFnPtr) -> Self {
112-
::core::assert!(!ptr.is_null());
113-
unsafe { ::core::mem::transmute(ptr) }
114-
}
70+
// WithAbi
71+
#[automatically_derived]
72+
impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::abi::key($crate::Abi::Rust)}> for $fn_type {
73+
type F = impl_fn!(@make_unsafe extern "Rust" fn($($ty),*) -> Ret, $safety);
11574
}
11675
#[automatically_derived]
117-
impl<Ret: 'static, $($ty: 'static),*> $crate::UnsafeFnPtr for $fn_type {
118-
unsafe fn invoke(&self, impl_fn!(@call_args ($($nm),*)): Self::Args) -> Self::Output {
119-
unsafe { (*self)($($nm),*) }
120-
}
76+
impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::abi::key($crate::Abi::C)}> for $fn_type {
77+
type F = impl_fn!(@make_unsafe extern "C" fn($($ty),*) -> Ret, $safety);
78+
}
79+
#[automatically_derived]
80+
impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::abi::key($crate::Abi::System)}> for $fn_type {
81+
type F = impl_fn!(@make_unsafe extern "system" fn($($ty),*) -> Ret, $safety);
82+
}
83+
#[cfg(has_abi_cdecl)]
84+
#[automatically_derived]
85+
impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::abi::key($crate::Abi::Cdecl)}> for $fn_type {
86+
type F = impl_fn!(@make_unsafe extern "cdecl" fn($($ty),*) -> Ret, $safety);
87+
}
88+
#[cfg(has_abi_stdcall)]
89+
#[automatically_derived]
90+
impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::abi::key($crate::Abi::Stdcall)}> for $fn_type {
91+
type F = impl_fn!(@make_unsafe extern "stdcall" fn($($ty),*) -> Ret, $safety);
92+
}
93+
#[cfg(has_abi_fastcall)]
94+
#[automatically_derived]
95+
impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::abi::key($crate::Abi::Fastcall)}> for $fn_type {
96+
type F = impl_fn!(@make_unsafe extern "fastcall" fn($($ty),*) -> Ret, $safety);
97+
}
98+
#[cfg(has_abi_win64)]
99+
#[automatically_derived]
100+
impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::abi::key($crate::Abi::Win64)}> for $fn_type {
101+
type F = impl_fn!(@make_unsafe extern "win64" fn($($ty),*) -> Ret, $safety);
102+
}
103+
#[cfg(has_abi_sysv64)]
104+
#[automatically_derived]
105+
impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::abi::key($crate::Abi::Sysv64)}> for $fn_type {
106+
type F = impl_fn!(@make_unsafe extern "sysv64" fn($($ty),*) -> Ret, $safety);
107+
}
108+
#[cfg(has_abi_aapcs)]
109+
#[automatically_derived]
110+
impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::abi::key($crate::Abi::Aapcs)}> for $fn_type {
111+
type F = impl_fn!(@make_unsafe extern "aapcs" fn($($ty),*) -> Ret, $safety);
121112
}
122-
123-
// WithSafety
124-
#[automatically_derived] impl<Ret: 'static, $($ty: 'static),*> $crate::WithSafety<{true}, $fn_type> for $fn_type { type F = extern $call_conv fn($($ty),*) -> Ret; }
125-
#[automatically_derived] impl<Ret: 'static, $($ty: 'static),*> $crate::WithSafety<{false}, $fn_type> for $fn_type { type F = $fn_type; }
126-
127-
cfg_all!(feature = "nightly" {
128-
// HasAbi
129-
#[automatically_derived] impl<Ret: 'static, $($ty: 'static),*> $crate::HasAbi<{$crate::Abi::$abi_ident}> for $fn_type {}
130-
131-
// WithAbi
132-
#[automatically_derived] impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Rust}, $fn_type> for $fn_type { type F = unsafe extern "Rust" fn($($ty),*) -> Ret; }
133-
#[automatically_derived] impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::C}, $fn_type> for $fn_type { type F = unsafe extern "C" fn($($ty),*) -> Ret; }
134-
#[automatically_derived] impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::System}, $fn_type> for $fn_type { type F = unsafe extern "system" fn($($ty),*) -> Ret; }
135-
#[cfg(has_abi_cdecl)]
136-
#[automatically_derived] impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Cdecl}, $fn_type> for $fn_type { type F = unsafe extern "cdecl" fn($($ty),*) -> Ret; }
137-
#[cfg(has_abi_stdcall)]
138-
#[automatically_derived] impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Stdcall}, $fn_type> for $fn_type { type F = unsafe extern "stdcall" fn($($ty),*) -> Ret; }
139-
#[cfg(has_abi_fastcall)]
140-
#[automatically_derived] impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Fastcall}, $fn_type> for $fn_type { type F = unsafe extern "fastcall" fn($($ty),*) -> Ret; }
141-
#[cfg(has_abi_win64)]
142-
#[automatically_derived] impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Win64}, $fn_type> for $fn_type { type F = unsafe extern "win64" fn($($ty),*) -> Ret; }
143-
#[cfg(has_abi_sysv64)]
144-
#[automatically_derived] impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Sysv64}, $fn_type> for $fn_type { type F = unsafe extern "sysv64" fn($($ty),*) -> Ret; }
145-
#[cfg(has_abi_aapcs)]
146-
#[automatically_derived] impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Aapcs}, $fn_type> for $fn_type { type F = unsafe extern "aapcs" fn($($ty),*) -> Ret; }
147-
});
148113
};
149114

150115
(@count ()) => {
@@ -154,6 +119,30 @@ macro_rules! impl_fn {
154119
1 + impl_fn!(@count ($($tl)*))
155120
};
156121

122+
(@make_unsafe $fn_type:ty, true) => {
123+
$fn_type
124+
};
125+
(@make_unsafe extern $abi:literal fn($($args:ty),*) -> $ret:ty, false) => {
126+
unsafe extern $abi fn($($args),*) -> $ret
127+
};
128+
129+
(@impl_safe_fn_type ($($nm:ident : $ty:ident),*), $fn_type:ty, true) => {
130+
#[automatically_derived]
131+
impl<Ret: 'static, $($ty: 'static),*> $crate::SafeFnPtr for $fn_type {
132+
fn invoke(&self, impl_fn!(@call_args ($($nm),*)): Self::Args) -> Self::Output {
133+
(*self)($($nm),*)
134+
}
135+
}
136+
};
137+
(@impl_safe_fn_type ($($nm:ident : $ty:ident),*), $fn_type:ty, false) => {
138+
#[automatically_derived]
139+
impl<Ret: 'static, $($ty: 'static),*> $crate::UnsafeFnPtr for $fn_type {
140+
unsafe fn invoke(&self, impl_fn!(@call_args ($($nm),*)): Self::Args) -> Self::Output {
141+
unsafe { (*self)($($nm),*) }
142+
}
143+
}
144+
};
145+
157146
(@call_args ($single:ident)) => {
158147
($single,)
159148
};

0 commit comments

Comments
 (0)