closure_ffi/traits.rs
1//! Traits that `closure-ffi` uses to power its functionality.
2
3use crate::Box;
4
5/// Dummy trait implemented by every type.
6///
7/// As such, its trait object vtable only contains the drop impl for the type. Used to type erase
8/// the closure type in [`BareFn`](crate::BareFn) and friends.
9pub trait Any {}
10impl<T: ?Sized> Any for T {}
11
12/// Trait to construct a [`Box<dyn Trait>`] from a type implementing
13/// [`Unsize<dyn Trait>`](core::marker::Unsize).
14///
15/// Since [`Unsize<T>`](core::marker::Unsize) is gated behind the `unsize` nightly feature,
16/// on stable Rust this trait is only implemented for:
17/// - [`dyn Any + '_`](Any)
18/// - [`dyn Send + '_`](Send)
19/// - [`dyn Sync + '_`](Sync)
20/// - `dyn Send + Sync + '_`
21///
22/// Enable the `unstable` feature to support all possible coercions.
23///
24/// # Safety
25/// - `T` must be some trait object type `dyn Trait + Markers + 'a`, where `Markers` are optional
26/// marker traits (e.g. [`Send`] and [`Sync`]).
27/// - Given the same `T` as above, implementers must also implement `Trait`, `Markers` and outlive
28/// `'a`.
29pub unsafe trait ToBoxedDyn<T: ?Sized> {
30 /// Constructs a [`Box<T>`] from `Self`, coercing into the unsized type.
31 fn to_boxed_unsize(value: Self) -> Box<T>;
32}
33
34#[cfg(not(feature = "unstable"))]
35unsafe impl<'a, T: 'a> ToBoxedDyn<dyn Any + 'a> for T {
36 fn to_boxed_unsize(value: Self) -> Box<dyn Any + 'a> {
37 Box::new(value)
38 }
39}
40
41#[cfg(not(feature = "unstable"))]
42unsafe impl<'a, T: Send + 'a> ToBoxedDyn<dyn Send + 'a> for T {
43 fn to_boxed_unsize(value: Self) -> Box<dyn Send + 'a> {
44 Box::new(value)
45 }
46}
47
48#[cfg(not(feature = "unstable"))]
49unsafe impl<'a, T: Sync + 'a> ToBoxedDyn<dyn Sync + 'a> for T {
50 fn to_boxed_unsize(value: Self) -> Box<dyn Sync + 'a> {
51 Box::new(value)
52 }
53}
54
55#[cfg(not(feature = "unstable"))]
56unsafe impl<'a, T: Send + Sync + 'a> ToBoxedDyn<dyn Send + Sync + 'a> for T {
57 fn to_boxed_unsize(value: Self) -> Box<dyn Send + Sync + 'a> {
58 Box::new(value)
59 }
60}
61
62#[cfg(feature = "unstable")]
63// SAFETY:
64// - we restrict T to be a `dyn Trait`, not just any DST,
65// - the `Unsize` impl guarantees implementation of `T` by `U`
66unsafe impl<T: ?Sized, U: core::marker::Unsize<T>> ToBoxedDyn<T> for U
67where
68 T: core::ptr::Pointee<Metadata = core::ptr::DynMetadata<T>>,
69{
70 fn to_boxed_unsize(value: Self) -> Box<T> {
71 Box::<U>::new(value)
72 }
73}
74
75/// Trait implemented by unsafe function pointer types of up to 12 arguments.
76///
77/// Allows introspection of the function's calling convention, arguments, return type, and provides
78/// a `call` method for invoking the function.
79///
80/// # Limitations
81/// The trait cannot be automatically implemented for higher-kinded (i.e. `for <'a> fn`) bare
82/// functions. For these, use the [`bare_hrtb!`](crate::bare_hrtb) macro to create a transparent
83/// wrapper type which implements the trait. Furthermore, the trait cannot be implemented *at all*
84/// for higher-kinded bare functions which have more than 3 independent lifetimes.
85///
86/// # Safety
87/// - The trait *must not* be implemented on a type that is not `#[repr(transparent)]` with a
88/// function pointer, i.e. has a different size/alignment.
89///
90/// - When implemented on a non-function pointer type that is `#[repr(transparent)]` to a function
91/// pointer, all associated types ([`CC`][`FnPtr::CC`], [`Args`](FnPtr::Args) and
92/// [`Ret`](FnPtr::Ret)) must be consistent with the function pointer.
93pub unsafe trait FnPtr: Sized + Copy + Send + Sync {
94 /// Calling convention of the bare function, as a ZST marker type.
95 type CC: Default;
96
97 #[cfg(all(not(doc), feature = "tuple_trait"))]
98 /// The arguments of the function, as a tuple.
99 ///
100 /// This is a GAT with 3 independent lifetimes to support most higher-kinded bare functions.
101 type Args<'a, 'b, 'c>: core::marker::Tuple;
102
103 #[cfg(any(doc, not(feature = "tuple_trait")))]
104 #[cfg_attr(docsrs, doc(cfg(all())))]
105 /// The arguments of the function, as a tuple.
106 ///
107 /// This is a GAT with 3 independent lifetimes to support most higher-kinded bare functions.
108 ///
109 /// When the `tuple_trait` crate feature is enabled, this associated type has a
110 /// [`core::marker::Tuple`] bound. Note that this also requires the `tuple_trait` nightly
111 /// feature.
112 type Args<'a, 'b, 'c>;
113
114 /// The return type of the function.
115 ///
116 /// This is a GAT with 3 independent lifetimes to support most higher-kinded bare functions.
117 type Ret<'a, 'b, 'c>;
118
119 /// Calls self.
120 ///
121 /// # Safety
122 /// The same function-specific safety invariants must be upheld as when calling it directly.
123 unsafe fn call<'a, 'b, 'c>(self, args: Self::Args<'a, 'b, 'c>) -> Self::Ret<'a, 'b, 'c>;
124
125 /// Creates `Self` from an untyped pointer.
126 ///
127 /// # Safety
128 /// The untyped pointer must point to a valid instance of `Self`.
129 unsafe fn from_ptr(ptr: *const ()) -> Self;
130
131 /// Casts `self` to an untyped pointer.
132 fn to_ptr(self) -> *const ();
133
134 /// Creates a [`FnOnceThunk`] implementation from a closure taking the same arguments as this
135 /// function pointer.
136 fn make_once_thunk<F>(fun: F) -> impl FnOnceThunk<Self>
137 where
138 F: for<'a, 'b, 'c> PackedFnOnce<'a, 'b, 'c, Self>;
139
140 /// Creates a [`FnMutThunk`] implementation from a closure taking the same arguments as this
141 /// function pointer.
142 fn make_mut_thunk<F>(fun: F) -> impl FnMutThunk<Self>
143 where
144 F: for<'a, 'b, 'c> PackedFnMut<'a, 'b, 'c, Self>;
145
146 /// Creates a [`FnThunk`] implementation from a closure taking the same arguments as this
147 /// function pointer.
148 fn make_thunk<F>(fun: F) -> impl FnThunk<Self>
149 where
150 F: for<'a, 'b, 'c> PackedFn<'a, 'b, 'c, Self>;
151}
152
153/// Trait implemented by (`CC`, [`FnOnce`]) tuples used to generate a bare function thunk template,
154/// where `CC` is a calling convention marker type.
155///
156/// # Safety
157/// This trait is internal to the library and is not meant to be directly implemented by downstream
158/// crates.
159///
160/// # Why implement on tuples?
161/// Implenting on (calling-convention, closure) tuples instead of only the closure is done for two
162/// reasons:
163/// - It allows type-infering `B` from the calling convention and a closure with annotated
164/// parameters, which is highly desirable for the constructor API of [`BareFn`](crate::BareFn) and
165/// friends.
166/// - The [`bare_hrtb`](crate::bare_hrtb) macro can be used by downstream crates to generate
167/// implementations of this trait for specific higher-ranked bare functions. This is only possible
168/// if a local type is present in both the trait generic parameters and the implementor. By
169/// implementing on tuples, we can thus use a local type for the calling convention.
170pub unsafe trait FnOnceThunk<B: FnPtr>: Sized {
171 /// Type-erased bare function thunk template calling `self` by move. Internal to the library.
172 const THUNK_TEMPLATE_ONCE: *const u8;
173
174 /// Calls the closure making up this [`FnOnceThunk`] by value.
175 ///
176 /// # Safety
177 /// The same function-specific safety invariants must be upheld as when calling the underlying
178 /// closure directly.
179 unsafe fn call_once<'a, 'b, 'c>(self, args: B::Args<'a, 'b, 'c>) -> B::Ret<'a, 'b, 'c>;
180}
181
182/// Trait implemented by (`CC`, [`FnMut`]) tuples used to generate a bare function thunk template,
183/// where `CC` is a calling convention marker type.
184///
185/// We include `CC` in the type parameters even though it can be fetched from `B` has it enables
186/// much richer type inference in the construction API of [`BareFn`](crate::BareFn) and friends.
187///
188/// # Safety
189/// This trait is internal to the library and is not meant to be directly implemented by downstream
190/// crates.
191///
192/// # Why implement on tuples?
193/// Implenting on (calling-convention, closure) tuples instead of only the closure is done for two
194/// reasons:
195/// - It allows type-infering `B` from the calling convention and a closure with annotated
196/// parameters, which is highly desirable for the constructor API of [`BareFn`](crate::BareFn) and
197/// friends.
198/// - The [`bare_hrtb`](crate::bare_hrtb) macro can be used by downstream crates to generate
199/// implementations of this trait for specific higher-ranked bare functions. This is only possible
200/// if a local type is present in both the trait generic parameters and the implementor. By
201/// implementing on tuples, we can thus use a local type for the calling convention.
202pub unsafe trait FnMutThunk<B: FnPtr>: FnOnceThunk<B> {
203 /// Type-erased bare function thunk template calling `self` by mutable reference. Internal to
204 /// the library.
205 const THUNK_TEMPLATE_MUT: *const u8;
206
207 /// Calls the closure making up this [`FnMutThunk`] by mutable reference.
208 ///
209 /// # Safety
210 /// The same function-specific safety invariants must be upheld as when calling the underlying
211 /// closure directly.
212 unsafe fn call_mut<'a, 'b, 'c>(&mut self, args: B::Args<'a, 'b, 'c>) -> B::Ret<'a, 'b, 'c>;
213}
214
215/// Trait implemented by (`CC`, [`Fn`]) tuples used to generate a bare function thunk template,
216/// where `CC` is a calling convention marker type.
217///
218/// We include `CC` in the type parameters even though it can be fetched from `B` has it enables
219/// much richer type inference in the construction API of [`BareFn`](crate::BareFn) and friends.
220///
221/// # Safety
222/// This trait is internal to the library and is not meant to be directly implemented by downstream
223/// crates.
224///
225/// # Why implement on tuples?
226/// Implenting on (calling-convention, closure) tuples instead of only the closure is done for two
227/// reasons:
228/// - It allows type-infering `B` from the calling convention and a closure with annotated
229/// parameters, which is highly desirable for the constructor API of [`BareFn`](crate::BareFn) and
230/// friends.
231/// - The [`bare_hrtb`](crate::bare_hrtb) macro can be used by downstream crates to generate
232/// implementations of this trait for specific higher-ranked bare functions. This is only possible
233/// if a local type is present in both the trait generic parameters and the implementor. By
234/// implementing on tuples, we can thus use a local type for the calling convention.
235pub unsafe trait FnThunk<B: FnPtr>: FnMutThunk<B> {
236 /// Type-erased bare function thunk template calling `self` by immutable reference. Internal to
237 /// the library.
238 const THUNK_TEMPLATE: *const u8;
239
240 /// Calls the closure making up this [`FnThunk`] by value.
241 ///
242 /// # Safety
243 /// The same function-specific safety invariants must be upheld as when calling the underlying
244 /// closure directly.
245 unsafe fn call<'a, 'b, 'c>(&self, args: B::Args<'a, 'b, 'c>) -> B::Ret<'a, 'b, 'c>;
246}
247
248/// Trait alias for [`FnOnce(B::Args<'a, 'b, 'c>) -> B::Ret<'a, 'b, 'c>`](FnOnce).
249///
250/// This is necessary to express the return type of [`FnPtr::make_once_thunk`].
251pub trait PackedFnOnce<'a, 'b, 'c, B: FnPtr>:
252 FnOnce(B::Args<'a, 'b, 'c>) -> B::Ret<'a, 'b, 'c>
253{
254}
255
256impl<'a, 'b, 'c, B: FnPtr, F> PackedFnOnce<'a, 'b, 'c, B> for F where
257 F: FnOnce(B::Args<'a, 'b, 'c>) -> B::Ret<'a, 'b, 'c>
258{
259}
260
261/// Trait alias for [`FnMut(B::Args<'a, 'b, 'c>) -> B::Ret<'a, 'b, 'c>`](FnMut).
262///
263/// This is necessary to express the return type of [`FnPtr::make_mut_thunk`].
264pub trait PackedFnMut<'a, 'b, 'c, B: FnPtr>:
265 FnMut(B::Args<'a, 'b, 'c>) -> B::Ret<'a, 'b, 'c>
266{
267}
268
269impl<'a, 'b, 'c, B: FnPtr, F> PackedFnMut<'a, 'b, 'c, B> for F where
270 F: FnMut(B::Args<'a, 'b, 'c>) -> B::Ret<'a, 'b, 'c>
271{
272}
273
274/// Trait alias for [`Fn(B::Args<'a, 'b, 'c>) -> B::Ret<'a, 'b, 'c>`](Fn).
275///
276/// This is necessary to express the return type of [`FnPtr::make_thunk`].
277pub trait PackedFn<'a, 'b, 'c, B: FnPtr>: Fn(B::Args<'a, 'b, 'c>) -> B::Ret<'a, 'b, 'c> {}
278
279impl<'a, 'b, 'c, B: FnPtr, F> PackedFn<'a, 'b, 'c, B> for F where
280 F: Fn(B::Args<'a, 'b, 'c>) -> B::Ret<'a, 'b, 'c>
281{
282}