crossmist/
fns.rs

1//! Utilities for passing function callbacks between processes.
2//!
3//! It is common to use callbacks to specialize function behavior. Capturing lambdas play an
4//! especially big role in this. They are, however, of complex opaque types that cannot be
5//! inspected. Therefore, passing lambdas is not just complicated because they would have to be of
6//! type `dyn Object + Fn() -> ()`, which Rust does not support at the moment, but downright
7//! impossible in case of captures.
8//!
9//! To fix the following code:
10//!
11//! ```compile_fail
12//! use crossmist::{func, main, Object};
13//!
14//! #[main]
15//! fn main() {
16//!     let x = 7;
17//!     println!("{}", go.run(5, Box::new(|y| x + y)).unwrap());
18//! }
19//!
20//! #[func]
21//! fn go(x: i32, f: Box<dyn Object + Fn(i32) -> i32>) -> i32 {
22//!     f(x)
23//! }
24//! ```
25//!
26//! ...we have to use a macro, and also a different invocation syntax:
27//!
28//! ```rust
29//! use crossmist::{FnObject, func, lambda, main};
30//!
31//! #[main]
32//! fn main() {
33//!     let x = 7;
34//!     println!("{}", go.run(5, lambda! { move(x: i32) |y: i32| -> i32 { x + y } }).unwrap());
35//! }
36//!
37//! #[func]
38//! fn go(x: i32, f: Box<dyn FnObject<(i32,), Output = i32>>) -> i32 {
39//!     f.call_object((x,))
40//! }
41//! ```
42//!
43//! The macro syntax is somewhat similar to that of capturing lambdas. `call_object` is similar to
44//! [`std::ops::Fn::call`]. If you're using nightly Rust, you can directly do `f(x)` if you opt in
45//! by enabling the `nightly` feature.
46//!
47//! Another complication is when the callback should capture a non-copyable value (e.g. [`Box`]) and
48//! then be called multiple times. This cannot be detected automatically, so slightly different
49//! syntax is used:
50//!
51//! ```rust
52//! use crossmist::{FnObject, func, lambda, main};
53//!
54//! #[main]
55//! fn main() {
56//!     let x = Box::new(7);
57//!     println!("{}", go.run(5, lambda! { move(&x: &Box<i32>) |y: i32| -> i32 { **x + y } }).unwrap());
58//! }
59//!
60//! #[func]
61//! fn go(x: i32, f: Box<dyn FnObject<(i32,), Output = i32>>) -> i32 {
62//!     f.call_object((x,))
63//! }
64//! ```
65//!
66//! Similarly, `&mut x` can be used if the object is to be modified. Note that this still moves `x`
67//! into the lambda.
68//!
69//! Under the hood, the macro uses currying, replacing `|y| x + y` with `|x, y| x + y` with a
70//! pre-determined `x` variable, and makes `|x, y| x + y` a callable [`Object`] by using `#[func]`:
71//!
72//! ```rust
73//! use crossmist::{BindValue, FnObject, func, main};
74//!
75//! #[main]
76//! fn main() {
77//!     #[func]
78//!     fn add(x: i32, y: i32) -> i32 {
79//!         x + y
80//!     }
81//!
82//!     let x = 7;
83//!     println!("{}", go.run(5, Box::new(add.bind_value(x))).unwrap());
84//! }
85//!
86//! #[func]
87//! fn go(x: i32, f: Box<dyn FnObject<(i32,), Output = i32>>) -> i32 {
88//!     f.call_object((x,))
89//! }
90//! ```
91
92use crate::{relocation::RelocatablePtr, Object};
93use paste::paste;
94use std::marker::PhantomData;
95use std::ops::Deref;
96
97macro_rules! impl_fn {
98    (
99        impl[$($generic_bounds:tt)*] FnOnce<$args_ty:ty, Output = $output:ty> for $target:ty $(where[$($where:tt)*])? =
100        $(#[$attr:meta])*
101        |$self:tt, $args:tt| {
102            $($body:tt)*
103        }
104    ) => {
105        #[cfg(feature = "nightly")]
106        impl<$($generic_bounds)*> std::ops::FnOnce<$args_ty> for $target $(where $($where)*)? {
107            type Output = $output;
108            $(#[$attr])*
109            #[allow(unused_mut)]
110            extern "rust-call" fn call_once(mut $self, $args: $args_ty) -> Self::Output {
111                $($body)*
112            }
113        }
114        #[cfg(not(feature = "nightly"))]
115        impl<$($generic_bounds)*> FnOnceObject<$args_ty> for $target $(where $($where)*)? {
116            type Output = $output;
117            $(#[$attr])*
118            #[allow(unused_mut)]
119            fn call_object_once(mut $self, $args: $args_ty) -> Self::Output {
120                $($body)*
121            }
122            fn call_object_box(self: Box<Self>, args: $args_ty) -> Self::Output {
123                (*self).call_object_once(args)
124            }
125        }
126    };
127
128    (
129        impl[$($generic_bounds:tt)*] FnMut<$args_ty:ty> for $target:ty $(where[$($where:tt)*])? =
130        $(#[$attr:meta])*
131        |$self:tt, $args:tt| {
132            $($body:tt)*
133        }
134    ) => {
135        #[cfg(feature = "nightly")]
136        impl<$($generic_bounds)*> std::ops::FnMut<$args_ty> for $target $(where $($where)*)? {
137            $(#[$attr])*
138            extern "rust-call" fn call_mut(&mut $self, $args: $args_ty) -> Self::Output {
139                $($body)*
140            }
141        }
142        #[cfg(not(feature = "nightly"))]
143        impl<$($generic_bounds)*> FnMutObject<$args_ty> for $target $(where $($where)*)? {
144            $(#[$attr])*
145            fn call_object_mut(&mut $self, $args: $args_ty) -> Self::Output {
146                $($body)*
147            }
148        }
149    };
150
151    (
152        impl[$($generic_bounds:tt)*] Fn<$args_ty:ty> for $target:ty  $(where[$($where:tt)*])?=
153        $(#[$attr:meta])*
154        |$self:tt, $args:tt| {
155            $($body:tt)*
156        }
157    ) => {
158        #[cfg(feature = "nightly")]
159        impl<$($generic_bounds)*> std::ops::Fn<$args_ty> for $target $(where $($where)*)? {
160            $(#[$attr])*
161            extern "rust-call" fn call(&$self, $args: $args_ty) -> Self::Output {
162                $($body)*
163            }
164        }
165        #[cfg(not(feature = "nightly"))]
166        impl<$($generic_bounds)*> FnObject<$args_ty> for $target $(where $($where)*)? {
167            $(#[$attr])*
168            fn call_object(&$self, $args: $args_ty) -> Self::Output {
169                $($body)*
170            }
171        }
172    };
173}
174
175#[allow(missing_debug_implementations)]
176#[doc(hidden)]
177#[derive(Object)]
178pub struct CallWrapper<T: Object>(pub T);
179
180/// A tuple.
181///
182/// Do not rely on the exact definition of this trait, as it may change depending on the enabled
183/// features.
184#[cfg(feature = "nightly")]
185pub trait Tuple: std::marker::Tuple {}
186#[cfg(feature = "nightly")]
187impl<T: std::marker::Tuple> Tuple for T {}
188
189#[cfg(not(feature = "nightly"))]
190mod private {
191    pub trait Sealed {}
192}
193/// A tuple.
194///
195/// Do not rely on the exact definition of this trait, as it may change depending on the enabled
196/// features.
197#[cfg(not(feature = "nightly"))]
198pub trait Tuple: private::Sealed {}
199#[cfg(not(feature = "nightly"))]
200macro_rules! decl_tuple {
201    () => {};
202    ($head:tt $($tail:tt)*) => {
203        impl<$($tail),*> private::Sealed for ($($tail,)*) {}
204        impl<$($tail),*> Tuple for ($($tail,)*) {}
205        decl_tuple!($($tail)*);
206    };
207}
208#[cfg(not(feature = "nightly"))]
209decl_tuple!(x T20 T19 T18 T17 T16 T15 T14 T13 T12 T11 T10 T9 T8 T7 T6 T5 T4 T3 T2 T1 T0);
210
211impl<T: Object> Deref for CallWrapper<T> {
212    type Target = T;
213    fn deref(&self) -> &T {
214        &self.0
215    }
216}
217
218#[doc(hidden)]
219pub trait InternalFnOnce<Args>: Object {
220    type Output;
221    fn call_object_once(self, args: Args) -> Self::Output;
222}
223impl_fn! {
224    impl[Args: Tuple, T: InternalFnOnce<Args>] FnOnce<Args, Output = T::Output> for CallWrapper<T> =
225    |self, args| {
226        self.0.call_object_once(args)
227    }
228}
229
230#[doc(hidden)]
231pub trait InternalFnMut<Args>: InternalFnOnce<Args> {
232    fn call_object_mut(&mut self, args: Args) -> Self::Output;
233}
234impl_fn! {
235    impl[Args: Tuple, T: InternalFnMut<Args>] FnMut<Args> for CallWrapper<T> = |self, args| {
236        self.0.call_object_mut(args)
237    }
238}
239
240#[doc(hidden)]
241pub trait InternalFn<Args>: InternalFnMut<Args> {
242    fn call_object(&self, args: Args) -> Self::Output;
243}
244impl_fn! {
245    impl[Args: Tuple, T: InternalFn<Args>] Fn<Args> for CallWrapper<T> = |self, args| {
246        self.0.call_object(args)
247    }
248}
249
250/// A callable object that can be called at least once.
251///
252/// Do not implement this trait manually: the library gives no guarantees whether that is possible,
253/// portable, or stable.
254#[cfg(not(feature = "nightly"))]
255pub trait FnOnceObject<Args: Tuple>: Object {
256    /// Function return type.
257    type Output;
258    /// Invoke the function with the given argument tuple.
259    ///
260    /// # Example
261    ///
262    /// ```rust
263    /// use crossmist::{FnOnceObject, lambda};
264    ///
265    /// let s = "Hello, world!".to_string();
266    /// let mut increment = lambda! { move(s: String) || -> String { s } };
267    ///
268    /// assert_eq!(increment.call_object_once(()), "Hello, world!");
269    /// ```
270    fn call_object_once(self, args: Args) -> Self::Output;
271    /// Invoke a boxed function with the given argument tuple.
272    ///
273    /// This method is implemented as follows:
274    ///
275    /// ```ignore
276    /// fn call_object_box(self: Box<Self>, args: Args) -> Self::Output {
277    ///     (*self).call_object_once(args)
278    /// }
279    /// ```
280    ///
281    /// It enables `FnOnceObject<Args>` to be automatically implemented for
282    /// `Box<dyn FnOnceObject<Args>>`.
283    fn call_object_box(self: Box<Self>, args: Args) -> Self::Output;
284}
285/// A callable object that can be called at least once.
286///
287/// Do not implement this trait manually: the library gives no guarantees whether that is possible,
288/// portable, or stable.
289#[cfg(feature = "nightly")]
290pub trait FnOnceObject<Args: Tuple>: Object + std::ops::FnOnce<Args> {
291    /// Invoke the function with the given argument tuple.
292    ///
293    /// # Example
294    ///
295    /// ```rust
296    /// use crossmist::{FnOnceObject, lambda};
297    ///
298    /// let s = "Hello, world!".to_string();
299    /// let mut increment = lambda! { move(s: String) || -> String { s } };
300    ///
301    /// assert_eq!(increment.call_object_once(()), "Hello, world!");
302    /// ```
303    fn call_object_once(self, args: Args) -> Self::Output;
304    /// Invoke a boxed function with the given argument tuple.
305    ///
306    /// This method is implemented as follows:
307    ///
308    /// ```ignore
309    /// fn call_object_box(self: Box<Self>, args: Args) -> Self::Output {
310    ///     (*self).call_object_once(args)
311    /// }
312    /// ```
313    ///
314    /// It enables `FnOnceObject<Args>` to be automatically implemented for
315    /// `Box<dyn FnOnceObject<Args>>`.
316    fn call_object_box(self: Box<Self>, args: Args) -> Self::Output;
317}
318#[cfg(not(feature = "nightly"))]
319impl<Args: Tuple, T: FnOnceObject<Args> + ?Sized> FnOnceObject<Args> for Box<T>
320where
321    Box<T>: Object,
322{
323    type Output = T::Output;
324    fn call_object_once(self, args: Args) -> Self::Output {
325        self.call_object_box(args)
326    }
327    fn call_object_box(self: Box<Self>, args: Args) -> Self::Output {
328        (*self).call_object_once(args)
329    }
330}
331#[cfg(feature = "nightly")]
332impl<Args: Tuple, T: Object + std::ops::FnOnce<Args>> FnOnceObject<Args> for T {
333    fn call_object_once(self, args: Args) -> Self::Output {
334        self.call_once(args)
335    }
336    fn call_object_box(self: Box<Self>, args: Args) -> Self::Output {
337        self.call_once(args)
338    }
339}
340
341/// A callable object that can be called multiple times and might mutate state.
342///
343/// Do not implement this trait manually: the library gives no guarantees whether that is possible,
344/// portable, or stable.
345#[cfg(feature = "nightly")]
346pub trait FnMutObject<Args: Tuple>: FnOnceObject<Args> + std::ops::FnMut<Args> {
347    /// Invoke the function with the given argument tuple.
348    ///
349    /// # Example
350    ///
351    /// ```rust
352    /// use crossmist::{FnMutObject, lambda};
353    ///
354    /// let counter = 0;
355    /// let mut increment = lambda! {
356    ///     move(&mut counter: &mut i32) || -> i32 { *counter += 1; *counter }
357    /// };
358    ///
359    /// assert_eq!(increment.call_object_mut(()), 1);
360    /// assert_eq!(increment.call_object_mut(()), 2);
361    /// assert_eq!(increment.call_object_mut(()), 3);
362    /// ```
363    fn call_object_mut(&mut self, args: Args) -> Self::Output;
364}
365/// A callable object that can be called multiple times and might mutate state.
366///
367/// Do not implement this trait manually: the library gives no guarantees whether that is possible,
368/// portable, or stable.
369#[cfg(not(feature = "nightly"))]
370pub trait FnMutObject<Args: Tuple>: FnOnceObject<Args> {
371    /// Invoke the function with the given argument tuple.
372    ///
373    /// # Example
374    ///
375    /// ```rust
376    /// use crossmist::{FnMutObject, lambda};
377    ///
378    /// let counter = 0;
379    /// let mut increment = lambda! {
380    ///     move(&mut counter: &mut i32) || -> i32 { *counter += 1; *counter }
381    /// };
382    ///
383    /// assert_eq!(increment.call_object_mut(()), 1);
384    /// assert_eq!(increment.call_object_mut(()), 2);
385    /// assert_eq!(increment.call_object_mut(()), 3);
386    /// ```
387    fn call_object_mut(&mut self, args: Args) -> Self::Output;
388}
389#[cfg(feature = "nightly")]
390impl<Args: Tuple, T: Object + std::ops::FnMut<Args>> FnMutObject<Args> for T {
391    fn call_object_mut(&mut self, args: Args) -> Self::Output {
392        self.call_mut(args)
393    }
394}
395
396/// A callable object that can be called multiple times without mutating state.
397///
398/// Do not implement this trait manually: the library gives no guarantees whether that is possible,
399/// portable, or stable.
400#[cfg(feature = "nightly")]
401pub trait FnObject<Args: Tuple>: FnMutObject<Args> + std::ops::Fn<Args> {
402    /// Invoke the function with the given argument tuple.
403    ///
404    /// # Example
405    ///
406    /// ```rust
407    /// use crossmist::{FnObject, func};
408    ///
409    /// #[func]
410    /// fn add(a: i32, b: i32) -> i32 {
411    ///     a + b
412    /// }
413    ///
414    /// assert_eq!(add.call_object((5, 7)), 12);
415    /// ```
416    fn call_object(&self, args: Args) -> Self::Output;
417}
418/// A callable object that can be called multiple times without mutating state.
419///
420/// Do not implement this trait manually: the library gives no guarantees whether that is possible,
421/// portable, or stable.
422#[cfg(not(feature = "nightly"))]
423pub trait FnObject<Args: Tuple>: FnMutObject<Args> {
424    /// Invoke the function with the given argument tuple.
425    ///
426    /// # Example
427    ///
428    /// ```rust
429    /// use crossmist::{FnObject, func};
430    ///
431    /// #[func]
432    /// fn add(a: i32, b: i32) -> i32 {
433    ///     a + b
434    /// }
435    ///
436    /// assert_eq!(add.call_object((5, 7)), 12);
437    /// ```
438    fn call_object(&self, args: Args) -> Self::Output;
439}
440#[cfg(feature = "nightly")]
441impl<Args: Tuple, T: Object + std::ops::Fn<Args>> FnObject<Args> for T {
442    fn call_object(&self, args: Args) -> Self::Output {
443        self.call(args)
444    }
445}
446
447#[doc(hidden)]
448pub trait BindValue<Head: Object, Tail>: Object + Sized {
449    fn bind_value(self, head: Head) -> BoundValue<Self, Head>;
450}
451#[doc(hidden)]
452pub trait BindMut<Head: Object, Tail>: Object + Sized {
453    fn bind_mut(self, head: Head) -> BoundMut<Self, Head>;
454}
455#[doc(hidden)]
456pub trait BindRef<Head: Object, Tail>: Object + Sized {
457    fn bind_ref(self, head: Head) -> BoundRef<Self, Head>;
458}
459
460#[allow(missing_debug_implementations)]
461#[doc(hidden)]
462#[derive(Object)]
463pub struct BoundValue<Func: Object, Head: Object> {
464    pub func: Func,
465    pub head: Head,
466}
467#[allow(missing_debug_implementations)]
468#[doc(hidden)]
469#[derive(Object)]
470pub struct BoundMut<Func: Object, Head: Object> {
471    pub func: Func,
472    pub head: Head,
473}
474#[allow(missing_debug_implementations)]
475#[doc(hidden)]
476#[derive(Object)]
477pub struct BoundRef<Func: Object, Head: Object> {
478    pub func: Func,
479    pub head: Head,
480}
481
482macro_rules! reverse {
483    ([$($acc:tt)*]) => { ($($acc)*) };
484    ([$($acc:tt)*] $single:tt) => { reverse!([$single, $($acc)*]) };
485    ([$($acc:tt)*] $head:tt, $($tail:tt),*) => { reverse!([$head, $($acc)*] $($tail),*) };
486}
487
488macro_rules! decl_fn {
489    () => {};
490
491    ($head:tt $($tail:tt)*) => {
492        decl_fn!($($tail)*);
493
494        paste! {
495            impl<[<T $head>]: Object $(, [<T $tail>])*, Func: FnOnceObject<([<T $head>], $([<T $tail>]),*)>> BindValue<[<T $head>], ($([<T $tail>],)*)> for Func {
496                fn bind_value(self, head: [<T $head>]) -> BoundValue<Self, [<T $head>]> {
497                    BoundValue {
498                        func: self,
499                        head,
500                    }
501                }
502            }
503            impl<'a, [<T $head>]: 'a + Object $(, [<T $tail>])*, Func: FnOnceObject<(&'a mut [<T $head>], $([<T $tail>]),*)>> BindMut<[<T $head>], ($([<T $tail>],)*)> for Func {
504                fn bind_mut(self, head: [<T $head>]) -> BoundMut<Self, [<T $head>]> {
505                    BoundMut {
506                        func: self,
507                        head,
508                    }
509                }
510            }
511            impl<'a, [<T $head>]: 'a + Object $(, [<T $tail>])*, Func: FnOnceObject<(&'a [<T $head>], $([<T $tail>]),*)>> BindRef<[<T $head>], ($([<T $tail>],)*)> for Func {
512                fn bind_ref(self, head: [<T $head>]) -> BoundRef<Self, [<T $head>]> {
513                    BoundRef {
514                        func: self,
515                        head,
516                    }
517                }
518            }
519
520            impl_fn! {
521                impl[[<T $head>]: Object $(, [<T $tail>])*, Func: FnOnceObject<([<T $head>], $([<T $tail>]),*)>] FnOnce<($([<T $tail>],)*), Output = Func::Output> for BoundValue<Func, [<T $head>]> =
522                #[allow(unused_variables)]
523                |self, args| {
524                    self.func.call_object_once(reverse!([] $((args.$tail),)* (self.head)))
525                }
526            }
527            impl_fn! {
528                impl[[<T $head>]: Copy + Object $(, [<T $tail>])*, Func: FnMutObject<([<T $head>], $([<T $tail>]),*)>] FnMut<($([<T $tail>],)*)> for BoundValue<Func, [<T $head>]> =
529                #[allow(unused_variables)]
530                |self, args| {
531                    self.func.call_object_mut(reverse!([] $((args.$tail),)* (self.head)))
532                }
533            }
534            impl_fn! {
535                impl[[<T $head>]: Copy + Object $(, [<T $tail>])*, Func: FnObject<([<T $head>], $([<T $tail>]),*)>] Fn<($([<T $tail>],)*)> for BoundValue<Func, [<T $head>]> =
536                #[allow(unused_variables)]
537                |self, args| {
538                    self.func.call_object(reverse!([] $((args.$tail),)* (self.head)))
539                }
540            }
541
542            impl_fn! {
543                impl[[<T $head>]: Object $(, [<T $tail>])*, Output, Func: for<'a> FnOnceObject<(&'a mut [<T $head>], $([<T $tail>]),*), Output = Output>] FnOnce<($([<T $tail>],)*), Output = Output> for BoundMut<Func, [<T $head>]> =
544                #[allow(unused_variables)]
545                |self, args| {
546                    self.func.call_object_once(reverse!([] $((args.$tail),)* (&mut self.head)))
547                }
548            }
549            impl_fn! {
550                impl[[<T $head>]: Object $(, [<T $tail>])*, Output, Func: for<'a> FnMutObject<(&'a mut [<T $head>], $([<T $tail>]),*), Output = Output>] FnMut<($([<T $tail>],)*)> for BoundMut<Func, [<T $head>]> =
551                #[allow(unused_variables)]
552                |self, args| {
553                    self.func.call_object_mut(reverse!([] $((args.$tail),)* (&mut self.head)))
554                }
555            }
556
557            impl_fn! {
558                impl[[<T $head>]: Object $(, [<T $tail>])*, Output, Func: for<'a> FnOnceObject<(&'a [<T $head>], $([<T $tail>]),*), Output = Output>] FnOnce<($([<T $tail>],)*), Output = Output> for BoundRef<Func, [<T $head>]> =
559                #[allow(unused_variables)]
560                |self, args| {
561                    self.func.call_object_once(reverse!([] $((args.$tail),)* (&self.head)))
562                }
563            }
564            impl_fn! {
565                impl[[<T $head>]: Object $(, [<T $tail>])*, Output, Func: for<'a> FnMutObject<(&'a [<T $head>], $([<T $tail>]),*), Output = Output>] FnMut<($([<T $tail>],)*)> for BoundRef<Func, [<T $head>]> =
566                #[allow(unused_variables)]
567                |self, args| {
568                    self.func.call_object_mut(reverse!([] $((args.$tail),)* (&self.head)))
569                }
570            }
571            impl_fn! {
572                impl[[<T $head>]: Object $(, [<T $tail>])*, Output, Func: for<'a> FnObject<(&'a [<T $head>], $([<T $tail>]),*), Output = Output>] Fn<($([<T $tail>],)*)> for BoundRef<Func, [<T $head>]> =
573                #[allow(unused_variables)]
574                |self, args| {
575                    self.func.call_object(reverse!([] $((args.$tail),)* (&self.head)))
576                }
577            }
578        }
579    }
580}
581
582decl_fn!(x 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0);
583
584/// A short-cut for turning a (possible capturing) closure into an object function, just like as if
585/// `#[func]` was used.
586///
587/// Syntax is similar to that of closure, except that types of all arguments and the type of the
588/// return value are not inferred. Additionally, all moved values have to be listed manually,
589/// indicating how they are captured.
590///
591/// Simplest example:
592///
593/// ```rust
594/// # use crossmist::{lambda, main};
595/// #[main]
596/// fn main() {
597///     let func = lambda! { |a: i32, b: i32| -> i32 { a + b } };
598///     assert_eq!(func.run(5, 7).unwrap(), 12);
599/// }
600/// ```
601///
602/// With captures:
603///
604/// ```rust
605/// # use crossmist::{FnObject, FnOnceObject, func, lambda, main};
606/// #[main]
607/// fn main() {
608///     let a = 5;
609///     let func = lambda! { move(a: i32) |b: i32| -> i32 { a + b } };
610///     // run/spawn do not work directly, but you may still call/pass the function
611///     assert_eq!(func.call_object((7,)), 12);
612///     assert_eq!(gate.run(func, 7).unwrap(), 12);
613/// }
614///
615/// #[func]
616/// fn gate(f: Box<dyn FnOnceObject<(i32,), Output = i32>>, arg: i32) -> i32 {
617///     f.call_object_once((arg,))
618/// }
619/// ```
620///
621/// `f.call_object_once((arg,))` can be replaced with `f(arg)` if the `nightly` feature is enabled.
622///
623/// Captuing more complex objects (type annotations are provided for completeness and are
624/// unnecessary):
625///
626/// ```rust
627/// # use crossmist::{FnOnceObject, lambda, main};
628/// # #[main]
629/// # fn main() {
630/// let a = "Hello, ".to_string();
631/// // a is accessible by value when the lambda is executed
632/// let prepend_hello: Box<dyn FnOnceObject<(&str,), Output = String>> =
633///     lambda! { move(a: String) |b: &str| -> String { a + b } };
634/// assert_eq!(prepend_hello.call_object_once(("world!",)), "Hello, world!".to_string());
635/// // Can only be called once. The line below fails to compile when uncommented:
636/// // assert_eq!(prepend_hello.call_object_once(("world!",)), "Hello, world!".to_string());
637/// # }
638/// ```
639///
640/// ```rust
641/// # use crossmist::{FnMutObject, lambda, main};
642/// # #[main]
643/// # fn main() {
644/// let cache = vec![0, 1];
645/// // cache is accessible by a mutable reference when the lambda is executed
646/// let mut fibonacci: Box<dyn FnMutObject<(usize,), Output = u32>> = lambda! {
647///     move(&mut cache: &mut Vec<u32>) |n: usize| -> u32 {
648///         while cache.len() <= n {
649///             cache.push(cache[cache.len() - 2..].iter().sum());
650///         }
651///         cache[n]
652///     }
653/// };
654/// assert_eq!(fibonacci.call_object_mut((3,)), 2);
655/// // Can be called multiple types, but has to be mutable
656/// assert_eq!(fibonacci.call_object_mut((6,)), 8);
657/// # }
658/// ```
659///
660/// ```rust
661/// # use crossmist::{FnObject, lambda, main};
662/// # #[main]
663/// # fn main() {
664/// let s = "Hello, world!".to_string();
665/// // s is accessible by an immutable reference when the lambda is executed
666/// let count_occurrences: Box<dyn FnObject<(char,), Output = usize>> =
667///     lambda! { move(&s: &String) |c: char| -> usize { s.matches(c).count() } };
668/// assert_eq!(count_occurrences.call_object(('o',)), 2);
669/// // Can be called multiple times and be immutable
670/// assert_eq!(count_occurrences.call_object(('e',)), 1);
671/// # }
672/// ```
673#[macro_export]
674macro_rules! lambda {
675    // split || into | |
676    (|| $($items:tt)*) => {
677        $crate::lambda_parse! {
678            [],
679            [_unnamed],
680            | $($items)*
681        }
682    };
683    (|$($items:tt)*) => {
684        $crate::lambda_parse! {
685            [],
686            [_unnamed],
687            $($items)*
688        }
689    };
690    // split || into | |
691    (move($($moved_vars:tt)*) || $($items:tt)*) => {
692        $crate::lambda_parse! {
693            [],
694            [
695                $crate::lambda_bind! { [_unnamed], $($moved_vars)* }
696            ],
697            $($moved_vars)*, | $($items)*
698        }
699    };
700    (move($($moved_vars:tt)*) |$($items:tt)*) => {
701        $crate::lambda_parse! {
702            [],
703            [
704                $crate::lambda_bind! { [_unnamed], $($moved_vars)* }
705            ],
706            $($moved_vars)*, $($items)*
707        }
708    };
709}
710
711#[doc(hidden)]
712#[macro_export]
713macro_rules! lambda_parse {
714    (
715        [$($args:tt)*],
716        [$($append:tt)*],
717        , $($rest:tt)*
718    ) => {
719        $crate::lambda_parse! { [$($args)*], [$($append)*], $($rest)* }
720    };
721    (
722        [$($args:tt)*],
723        [$($append:tt)*],
724        &mut $name:ident: $type:ty, $($rest:tt)*
725    ) => {
726        $crate::lambda_parse! { [$($args)* $name: $type,], [$($append)*], $($rest)* }
727    };
728    (
729        [$($args:tt)*],
730        [$($append:tt)*],
731        $(&)? $name:ident: $type:ty, $($rest:tt)*
732    ) => {
733        $crate::lambda_parse! { [$($args)* $name: $type,], [$($append)*], $($rest)* }
734    };
735    (
736        [$($args:tt)*],
737        [$($append:tt)*],
738        &mut $name:ident: $type:ty| $($rest:tt)*
739    ) => {
740        $crate::lambda_parse! { [$($args)* $name: $type,], [$($append)*], |$($rest)* }
741    };
742    (
743        [$($args:tt)*],
744        [$($append:tt)*],
745        $(&)? $name:ident: $type:ty| $($rest:tt)*
746    ) => {
747        $crate::lambda_parse! { [$($args)* $name: $type,], [$($append)*], |$($rest)* }
748    };
749
750    (
751        [$($args:tt)*],
752        [$($append:tt)*],
753        | -> $return_type:ty { $($code:tt)* }
754    ) => {
755        {
756            #[$crate::func]
757            fn _unnamed($($args)*) -> $return_type {
758                $($code)*
759            }
760            {
761                #[allow(unused)]
762                use $crate::{BindValue, BindMut, BindRef};
763                ::std::boxed::Box::new($($append)*)
764            }
765        }
766    };
767}
768
769#[doc(hidden)]
770#[macro_export]
771macro_rules! lambda_bind {
772    ([$($acc:tt)*],) => { $($acc)* };
773
774    ([$($acc:tt)*], &mut $name:ident: $type:ty, $($rest:tt)*) => {
775        $crate::lambda_bind! { [$($acc)*.bind_mut($name)], $($rest)* }
776    };
777    ([$($acc:tt)*], &mut $name:ident: $type:ty) => {
778        $($acc)*.bind_mut($name)
779    };
780    ([$($acc:tt)*], &$name:ident: $type:ty, $($rest:tt)*) => {
781        $crate::lambda_bind! { [$($acc)*.bind_ref($name)], $($rest)* }
782    };
783    ([$($acc:tt)*], &$name:ident: $type:ty) => {
784        $($acc)*.bind_ref($name)
785    };
786    ([$($acc:tt)*], $name:ident: $type:ty, $($rest:tt)*) => {
787        $crate::lambda_bind! { [$($acc)*.bind_value($name)], $($rest)* }
788    };
789    ([$($acc:tt)*], $name:ident: $type:ty) => {
790        $($acc)*.bind_value($name)
791    };
792}
793
794/// Metaprogramming on `fn(...) -> ...` types.
795///
796/// This trait is not part of the stable API provided by crossmist.
797#[cfg(feature = "nightly")]
798pub trait FnPtr: std::marker::FnPtr {}
799#[cfg(feature = "nightly")]
800impl<T: std::marker::FnPtr> FnPtr for T {}
801
802#[cfg(not(feature = "nightly"))]
803mod fn_ptr_private {
804    pub trait Sealed {}
805}
806/// Metaprogramming on `fn(...) -> ...` types.
807///
808/// This trait is not part of the stable API provided by crossmist.
809#[cfg(not(feature = "nightly"))]
810pub trait FnPtr: Copy + Clone + fn_ptr_private::Sealed {
811    /// Convert the function pointer to a type-erased pointer.
812    fn addr(self) -> *const ();
813}
814
815/// A wrapper for `fn(...) -> ...` implementing `Object`.
816///
817/// This type enables you to pass `fn` and `unsafe fn` pointers between processes soundly without
818/// requiring [`lambda`] or [`crossmist::func`].
819///
820/// Creating the wrapper from a function pointer is `unsafe` because functions might not be
821/// available in the child process if they were created in runtime by JIT compilation or alike.
822///
823/// All function pointers are supported on nightly. Only function pointers with up to 20 arguments
824/// with no references of generic lifetimes are supported without the `nightly` feature flag.
825///
826/// # Example
827///
828/// These examples require the `nightly` feature to be enabled. [`FnObject::call_object`] can be
829/// used instead of direct calls on stable.
830///
831/// ```rust
832/// # use crossmist::fns::{FnObject, StaticFn};
833/// fn add(a: i32, b: i32) -> i32 {
834///     a + b
835/// }
836/// let add = unsafe { StaticFn::<fn(i32, i32) -> i32>::new(add) };
837/// let add: Box<dyn FnObject<(i32, i32), Output = i32>> = Box::new(add);
838/// assert_eq!(add(5, 7), 12);
839/// ```
840///
841/// ```rust
842/// # use crossmist::fns::{FnObject, StaticFn};
843/// let add = unsafe { StaticFn::<fn(i32, i32) -> i32>::new(|a, b| a + b) };
844/// let add: Box<dyn FnObject<(i32, i32), Output = i32>> = Box::new(add);
845/// assert_eq!(add(5, 7), 12);
846/// ```
847///
848/// This example works on stable without changes.
849///
850/// ```rust
851/// # use crossmist::fns::{FnObject, StaticFn};
852/// unsafe fn dangerous_read(p: *const i32) -> i32 {
853///     p.read()
854/// }
855/// let dangerous_read = unsafe { StaticFn::<unsafe fn(*const i32) -> i32>::new(dangerous_read) };
856/// let dangerous_read = dangerous_read.get_fn();
857/// unsafe {
858///     assert_eq!(dangerous_read(&123), 123);
859/// }
860/// ```
861///
862/// This example requires `nightly` because of references.
863///
864/// ```rust
865/// # use crossmist::fns::{FnObject, StaticFn};
866/// fn safe_read(p: &i32) -> i32 {
867///     *p
868/// }
869/// let safe_read = unsafe { StaticFn::<fn(&i32) -> i32>::new(safe_read) };
870/// let safe_read: Box<dyn FnObject<(&i32,), Output = i32>> = Box::new(safe_read);
871/// assert_eq!(safe_read(&123), 123);
872/// ```
873#[derive(Clone, Copy, Debug, Object)]
874pub struct StaticFn<F: FnPtr> {
875    ptr: RelocatablePtr<()>,
876    phantom: PhantomData<F>,
877}
878
879impl<F: FnPtr> StaticFn<F> {
880    /// Create a [`StaticFn`] from a function pointer.
881    ///
882    /// # Safety
883    ///
884    /// This is safe to call if the function pointer is obtained from an `fn` item or a closure
885    /// without captures.
886    pub unsafe fn new(f: F) -> Self {
887        Self {
888            ptr: RelocatablePtr(f.addr()),
889            phantom: PhantomData,
890        }
891    }
892
893    /// Extract a function pointer from a [`StaticFn`].
894    pub fn get_fn(self) -> F {
895        unsafe { std::mem::transmute_copy::<*const (), F>(&self.ptr.0) }
896    }
897
898    const _F_IS_POINTER_SIZED: () = assert!(
899        std::mem::size_of::<*const ()>() == std::mem::size_of::<F>(),
900        "An instance of FnPtr has a size not equal to the size of *const (). This should have \
901         been impossible."
902    );
903}
904
905macro_rules! impl_fn_pointer {
906    () => {};
907    ($head:tt $($tail:tt)*) => {
908        paste! {
909            #[cfg(not(feature = "nightly"))]
910            impl<Output, $([<T $tail>]),*> fn_ptr_private::Sealed for fn($([<T $tail>]),*) -> Output {}
911            #[cfg(not(feature = "nightly"))]
912            impl<Output, $([<T $tail>]),*> FnPtr for fn($([<T $tail>]),*) -> Output {
913                fn addr(self) -> *const () {
914                    self as *const ()
915                }
916            }
917
918            #[cfg(not(feature = "nightly"))]
919            impl<Output, $([<T $tail>]),*> fn_ptr_private::Sealed for unsafe fn($([<T $tail>]),*) -> Output {}
920            #[cfg(not(feature = "nightly"))]
921            impl<Output, $([<T $tail>]),*> FnPtr for unsafe fn($([<T $tail>]),*) -> Output {
922                fn addr(self) -> *const () {
923                    self as *const ()
924                }
925            }
926
927            impl_fn! {
928                impl[T: FnPtr, Output, $([<T $tail>]),*] FnOnce<($([<T $tail>],)*), Output = Output> for StaticFn<T> where[T: FnOnce($([<T $tail>]),*) -> Output] =
929                |self, args| {
930                    let ($([<a $tail>],)*) = args;
931                    self.get_fn()($([<a $tail>]),*)
932                }
933            }
934            impl_fn! {
935                impl[T: FnPtr, Output, $([<T $tail>]),*] FnMut<($([<T $tail>],)*)> for StaticFn<T> where[T: FnMut($([<T $tail>]),*) -> Output] =
936                |self, args| {
937                    let ($([<a $tail>],)*) = args;
938                    self.get_fn()($([<a $tail>]),*)
939                }
940            }
941            impl_fn! {
942                impl[T: FnPtr, Output, $([<T $tail>]),*] Fn<($([<T $tail>],)*)> for StaticFn<T> where[T: Fn($([<T $tail>]),*) -> Output] =
943                |self, args| {
944                    let ($([<a $tail>],)*) = args;
945                    self.get_fn()($([<a $tail>]),*)
946                }
947            }
948        }
949
950        impl_fn_pointer!($($tail)*);
951    };
952}
953impl_fn_pointer!(x 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0);