Skip to content

Commit be0c7b3

Browse files
committed
Fixup
1 parent b76741d commit be0c7b3

6 files changed

Lines changed: 88 additions & 48 deletions

File tree

README.md

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ The trait provides associated types and constants to introspect function pointer
1414

1515
### 1. Function Pointer Metadata
1616

17-
Every function pointer automatically implements [`FnPtr`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.FnPtr.html).
18-
Depending on the type, they also implement [`SafeFnPtr`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.SafeFnPtr.html), [`UnsafeFnPtr`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.UnsafeFnPtr.html), [`StaticFnPtr`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.StaticFnPtr.html) and [`HasAbi<Abi>`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.HasAbi.html).
19-
With it you can inspect the type of function:
17+
Every function pointer automatically implements [`FnPtr`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.FnPtr.html) as well as a bunch of other related traits. With these you can inspect the type of function pointers at compile time:
2018

2119
```rust
2220
use fn_ptr::{FnPtr, Abi};
@@ -26,7 +24,7 @@ type F = extern "C" fn(i32, i32) -> i32;
2624
assert_eq!(<F as FnPtr>::ARITY, 2);
2725
assert_eq!(<F as FnPtr>::IS_SAFE, true);
2826
assert_eq!(<F as FnPtr>::IS_EXTERN, true);
29-
assert_eq!(<F as FnPtr>::ABI, Abi::C);
27+
assert_eq!(<F as FnPtr>::ABI, Abi::C { unwind: false });
3028
```
3129

3230
There are also some const helper functons to do so ergonomically.
@@ -69,7 +67,7 @@ use fn_ptr::{with_abi, Abi};
6967

7068
type F = extern "C" fn(i32) -> i32;
7169

72-
type G = with_abi!(Abi::Sysv64, F);
70+
type G = with_abi!("sysv64", F);
7371
type H = with_abi!("C", extern "system" fn());
7472
```
7573

@@ -79,7 +77,7 @@ Or at the instance level:
7977
use fn_ptr::{FnPtr, abi};
8078
let rust_add: fn(i32, i32) -> i32 = |a, b| {a + b};
8179
// Safety: not actually safe!
82-
let c_add: extern "C" fn(i32, i32) -> i32 = unsafe { rust_add.with_abi::<{abi!("C")}>() };
80+
let c_add: extern "C" fn(i32, i32) -> i32 = unsafe { rust_add.with_abi::<abi!("C")>() };
8381
```
8482

8583
Note that this does not change the underlying ABI and should be used with caution.
@@ -90,11 +88,11 @@ To implement the traits for all function pointer types, there is a large [macro]
9088
For the conversion macros the crate relies on two traits: [`WithAbi`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.WithAbi.html) and [`WithSafety`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.WithSafety.html) that can also be used directly:
9189

9290
```rust
93-
use fn_ptr::{FnPtr, WithAbi, WithSafety, Abi};
91+
use fn_ptr::{FnPtr, WithAbi, WithSafety, marker::{SysV64, Unsafe}};
9492

9593
type F = extern "C" fn(i32);
96-
type G = <F as WithAbi<{Abi::Sysv64}>>::F;
97-
type U = <F as WithSafety<{false}>>::F;
94+
type G = <F as WithAbi<SysV64>>::F;
95+
type U = <F as WithSafety<Unsafe>::F;
9896
```
9997

10098
## License

src/base.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ use core::{
55
};
66

77
use crate::{
8-
AsSafe, AsUnsafe, WithAbi,
8+
AsSafe, AsUnsafe, WithAbi, WithSafety,
99
abi::Abi,
1010
make_safe, make_unsafe,
1111
marker::{self, Safe, Unsafe},
12-
with_abi,
12+
with_abi, with_safety,
1313
};
1414

1515
ffi_opaque::opaque! {
@@ -116,6 +116,18 @@ pub trait FnPtr:
116116
{
117117
unsafe { FnPtr::from_ptr(self.as_ptr()) }
118118
}
119+
120+
/// Produces a version of this function pointer with the given safety.
121+
///
122+
/// # Safety
123+
/// Caller must ensure that this function pointer is safe when casting to a safe function.
124+
#[must_use]
125+
unsafe fn with_safety<Safety: marker::Safety>(&self) -> with_safety!(Safety, Self)
126+
where
127+
Self: WithSafety<Safety>,
128+
{
129+
unsafe { FnPtr::from_ptr(self.as_ptr()) }
130+
}
119131
}
120132
}
121133

src/conversion.rs

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ impl<F: WithSafety<Unsafe>> AsUnsafe for F {}
4343

4444
cfg_tt::cfg_tt! {
4545
/// Helper trait that simplifies generic bounds when converting between funciton pointer types.
46+
// using has_abi_cdecl instead of stdcall, fastcall, thiscall is to reduce compile times
4647
pub trait Convertible:
4748
FnPtr
4849
+ WithAbi<marker::Rust>
@@ -58,12 +59,12 @@ pub trait Convertible:
5859
#[cfg(has_abi_aapcs)](+ WithAbi<marker::AapcsUnwind>)
5960
#[cfg(has_abi_cdecl)](+ WithAbi<marker::Cdecl>)
6061
#[cfg(has_abi_cdecl)](+ WithAbi<marker::CdeclUnwind>)
61-
#[cfg(has_abi_stdcall)](+ WithAbi<marker::Stdcall>)
62-
#[cfg(has_abi_stdcall)](+ WithAbi<marker::StdcallUnwind>)
63-
#[cfg(has_abi_fastcall)](+ WithAbi<marker::Fastcall>)
64-
#[cfg(has_abi_fastcall)](+ WithAbi<marker::FastcallUnwind>)
65-
#[cfg(has_abi_thiscall)](+ WithAbi<marker::Thiscall>)
66-
#[cfg(has_abi_thiscall)](+ WithAbi<marker::ThiscallUnwind>)
62+
#[cfg(has_abi_cdecl)](+ WithAbi<marker::Stdcall>)
63+
#[cfg(has_abi_cdecl)](+ WithAbi<marker::StdcallUnwind>)
64+
#[cfg(has_abi_cdecl)](+ WithAbi<marker::Fastcall>)
65+
#[cfg(has_abi_cdecl)](+ WithAbi<marker::FastcallUnwind>)
66+
#[cfg(has_abi_cdecl)](+ WithAbi<marker::Thiscall>)
67+
#[cfg(has_abi_cdecl)](+ WithAbi<marker::ThiscallUnwind>)
6768
#[cfg(has_abi_vectorcall)](+ WithAbi<marker::Vectorcall>)
6869
#[cfg(has_abi_vectorcall)](+ WithAbi<marker::VectorcallUnwind>)
6970
#[cfg(has_abi_sysv64)](+ WithAbi<marker::SysV64>)
@@ -88,12 +89,12 @@ where
8889
#[cfg(has_abi_aapcs)](+ WithAbi<marker::AapcsUnwind>)
8990
#[cfg(has_abi_cdecl)](+ WithAbi<marker::Cdecl>)
9091
#[cfg(has_abi_cdecl)](+ WithAbi<marker::CdeclUnwind>)
91-
#[cfg(has_abi_stdcall)](+ WithAbi<marker::Stdcall>)
92-
#[cfg(has_abi_stdcall)](+ WithAbi<marker::StdcallUnwind>)
93-
#[cfg(has_abi_fastcall)](+ WithAbi<marker::Fastcall>)
94-
#[cfg(has_abi_fastcall)](+ WithAbi<marker::FastcallUnwind>)
95-
#[cfg(has_abi_thiscall)](+ WithAbi<marker::Thiscall>)
96-
#[cfg(has_abi_thiscall)](+ WithAbi<marker::ThiscallUnwind>)
92+
#[cfg(has_abi_cdecl)](+ WithAbi<marker::Stdcall>)
93+
#[cfg(has_abi_cdecl)](+ WithAbi<marker::StdcallUnwind>)
94+
#[cfg(has_abi_cdecl)](+ WithAbi<marker::Fastcall>)
95+
#[cfg(has_abi_cdecl)](+ WithAbi<marker::FastcallUnwind>)
96+
#[cfg(has_abi_cdecl)](+ WithAbi<marker::Thiscall>)
97+
#[cfg(has_abi_cdecl)](+ WithAbi<marker::ThiscallUnwind>)
9798
#[cfg(has_abi_vectorcall)](+ WithAbi<marker::Vectorcall>)
9899
#[cfg(has_abi_vectorcall)](+ WithAbi<marker::VectorcallUnwind>)
99100
#[cfg(has_abi_sysv64)](+ WithAbi<marker::SysV64>)
@@ -107,31 +108,65 @@ where
107108
/// the specified ABI.
108109
///
109110
/// Accepts either:
110-
/// - an `Abi` value (e.g., `Abi::C`, `Abi::SysV64`), or
111+
/// - an [`Abi`](crate::marker::Abi) marker type (e.g., [`C`](crate::marker::C), [`SysV64`](crate::marker::SysV64)), or
111112
/// - a string literal (e.g., `"C"`, `"system"`, `"stdcall"`).
112113
///
113114
/// # Examples
114115
///
115116
/// ```rust
116117
/// # use fn_ptr::{with_abi, marker};
117-
/// type F = extern "C" fn(i32) -> i32;
118+
/// type F = with_abi!(marker::SysV64, extern "C" fn(i32) -> i32);
119+
/// // `F` is `extern "sysv64" fn(i32) -> i32`
118120
///
119-
/// type G = with_abi!(marker::SysV64, F);
120-
/// // `G` is `extern "sysv64" fn(i32) -> i32`
121-
///
122-
/// type H = with_abi!("C", extern "system" fn());
123-
/// // `H` is `extern "C" fn()`
121+
/// type G = with_abi!("C", extern "system" fn());
122+
/// // `G` is `extern "C" fn()`
124123
/// ```
125124
#[macro_export]
126125
macro_rules! with_abi {
127-
// ABI given as a path (Abi::C, Abi::SysV64, ...)
128126
( $abi:path, $ty:ty ) => {
129127
<$ty as $crate::WithAbi<$abi>>::F
130128
};
131129

132-
// ABI given as a string literal
133-
( $abi_lit:tt, $ty:ty ) => {
134-
<$ty as $crate::WithAbi<$crate::abi!($abi_lit)>>::F
130+
( $lit:tt, $ty:ty ) => {
131+
<$ty as $crate::WithAbi<$crate::abi!($lit)>>::F
132+
};
133+
}
134+
135+
/// Construct a function-pointer type identical to the given one but using
136+
/// the specified safety.
137+
///
138+
/// Accepts either:
139+
/// - an [`Safety`](crate::marker::Safety) marker type ([`Safe`](crate::marker::Safe) or [`Unsafe`](crate::marker::Unsafe))
140+
/// - safety keyword (`safe` or `unsafe`).
141+
/// - a boolean literal.
142+
///
143+
/// # Examples
144+
///
145+
/// ```rust
146+
/// # use fn_ptr::{with_safety, marker};
147+
/// type F = with_safety!(marker::Safe, unsafe extern "C" fn(i32) -> i32);
148+
/// // `F` is `extern "C" fn(i32) -> i32`
149+
///
150+
/// type G = with_safety!(unsafe, fn());
151+
/// // `G` is `unsafe fn()`
152+
/// ```
153+
#[macro_export]
154+
macro_rules! with_safety {
155+
( safe, $ty:ty ) => {
156+
$crate::with_safety!(@inner $crate::marker::Safe, $ty)
157+
};
158+
( unsafe, $ty:ty ) => {
159+
$crate::with_safety!(@inner $crate::marker::Unsafe, $ty)
160+
};
161+
( $safety:path, $ty:ty ) => {
162+
$crate::with_safety!(@inner $safety, $ty)
163+
};
164+
( $safety:tt, $ty:ty ) => {
165+
$crate::with_safety!(@inner $crate::safety!($safety), $ty)
166+
};
167+
168+
( @inner $safety:ty, $ty:ty ) => {
169+
<$ty as $crate::WithSafety<$safety>>::F
135170
};
136171
}
137172

src/impl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ macro_rules! impl_fn {
8585

8686
const ARITY: ::core::primitive::usize = <Self::ArityMarker as $crate::marker::Arity>::N;
8787
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>::KIND;
88+
const ABI: $crate::Abi = <$crate::marker::$abi_ident as $crate::marker::Abi>::VALUE;
8989
const IS_EXTERN: ::core::primitive::bool = !matches!(Self::ABI, $crate::Abi::Rust);
9090

9191
fn as_ptr(&self) -> $crate::UntypedFnPtr {

src/lib.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@
1515
//!
1616
//! ### 1. Function Pointer Metadata
1717
//!
18-
//! Every function pointer automatically implements [`FnPtr`].
19-
//! Depending on the type, they also implement [`SafeFnPtr`], [`UnsafeFnPtr`], and [`HasAbi<Abi>`].
20-
//! With it you can inspect the type of function:
18+
//! Every function pointer automatically implements [`FnPtr`] as well as a bunch of other related traits.
19+
//! With these you can inspect the type of function pointers at compile time:
2120
//!
2221
//! ```rust
2322
//! use fn_ptr::{FnPtr, Abi};
@@ -70,14 +69,12 @@
7069
//! You can also change the ABI of a function pointer at the type level:
7170
//!
7271
//! ```rust
73-
//! # #[cfg(nightly_build)] {
7472
//! use fn_ptr::{with_abi, Abi};
7573
//!
7674
//! type F = extern "C" fn(i32) -> i32;
7775
//!
78-
//! type G = with_abi!(Abi::Sysv64, F);
76+
//! type G = with_abi!("sysv64", F);
7977
//! type H = with_abi!("C", extern "system" fn());
80-
//! # }
8178
//! ```
8279
//!
8380
//! Or at the instance level:
@@ -98,13 +95,11 @@
9895
//! For the conversion macros the crate relies on two traits: [`WithAbi`] and [`WithSafety`] that can also be used directly:
9996
//!
10097
//! ```rust
101-
//! # #[cfg(nightly_build)] {
102-
//! use fn_ptr::{FnPtr, WithAbi, WithSafety, Abi};
98+
//! use fn_ptr::{FnPtr, WithAbi, WithSafety, marker::{SysV64, Unsafe}};
10399
//!
104100
//! type F = extern "C" fn(i32);
105-
//! type G = <F as WithAbi<{Abi::Sysv64}>>::F;
106-
//! type U = <F as WithSafety<{false}>>::F;
107-
//! # }
101+
//! type G = <F as WithAbi<SysV64>>::F;
102+
//! type U = <F as WithSafety<Unsafe>>::F;
108103
//! ```
109104
//!
110105
//! ## License

src/marker.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ pub trait Abi {
6464
const STR: &'static str;
6565

6666
/// The runtime [`Abi`] that represent this marker type.
67-
const KIND: crate::Abi;
67+
const VALUE: crate::Abi;
6868
}
6969

7070
/// Helper macro to implement [`Abi`].
@@ -78,7 +78,7 @@ macro_rules! define_abi_marker {
7878

7979
impl Abi for $name {
8080
const STR: &'static str = $lit;
81-
const KIND: $crate::Abi = $crate::Abi::from_str_const($lit).unwrap();
81+
const VALUE: $crate::Abi = $crate::Abi::from_str_const($lit).unwrap();
8282
}
8383
};
8484
}

0 commit comments

Comments
 (0)