I want to define a make_closure
function that works as follows:
- Takes a
wrapped
closure as input parameter. This closure produces anResult
type (i.e., can error). - Copies the initial state of
wrap
in thecopy
variable. - Takes a
handler
closure as input parameter. - Returns a boxed closure that works as follows:
- When the boxed closure is invoked, it invokes the
wrapped
closure. - If
wrapped
returnsOk
, then it returnsRetval::Same
. - If
wrapped
returnsError
, then it invokes thehandler
closure, invokesmake_closure
by passingcopy
andhandler
, and returns the result of the function call in form ofRetval::Failure
.
- When the boxed closure is invoked, it invokes the
enum Retval {
Same,
Failure(Box<dyn FnMut() -> Retval>),
}
fn make_closure<E>(mut wrapped: impl FnMut() -> Result<(), E> + Clone + 'static, mut handler: impl FnMut(E) + 'static) -> Box<dyn FnMut() -> Retval> {
Box::new(move || {
let copy = wrapped.clone();
return match wrapped() {
Ok(()) => { Retval::Same }
Err(error) => {
handler(error);
Retval::Failure(make_closure(copy, handler))
}
};
})
}
fn main() {
let mut counter = 0;
let mut n_failures = 0;
let mut cl = make_closure::<u32>(move || {
counter += 1;
println!("Closure invoked. Counter: {counter}");
Ok(()) // Depending on some logic, returns Ok or Err
}, move |error| {
n_failures += 1;
println!("Handler invoked. Failures so far: {n_failures}");
});
cl();
}
However, the compiler produces the following error:
error[E0507]: cannot move out of `handler`, a captured variable in an `FnMut` closure
--> src/main.rs:13:52
|
6 | fn make_closure<E>(mut cl: impl FnMut() -> Result<(), E> + Clone + 'static, mut handler: impl FnMut(E) + 'static) -> Box<dyn FnMut() -> R...
| ----------- captured outer variable
7 | Box::new(move || {
| ------- captured by this `FnMut` closure
...
13 | Retval::Failure(make_closure(copy, handler))
| ^^^^^^^ move occurs because `handler` has type `impl FnMut(E) + 'static`, which does not implement the `Copy` trait
I am out of ideas for solving this issue. Can you recommend an alternative approach?