I'm trying to pass multiple closures to a struct and store them as boxed trait objects. These closures are wrapped in a thread-safe (Send, Sync) and clone-able (Clone) struct.
use std::thread;
// make trait alias
trait SafeFnMut: FnMut() + Send + Sync {}
impl<F> SafeFnMut for F where F: FnMut() + Send + Sync {}
#[derive(Clone, Debug)]
struct WithCall<F> where F: Sized {
fp: Box<F>,
}
impl<F> WithCall<F> where F: SafeFnMut {
// boxing the closure here
pub fn new(fp: F) -> Self {
WithCall { fp: Box::new(fp) }
}
pub fn run(&mut self) {
(self.fp)()
}
}
struct HasWithCall<T> where T: SafeFnMut {
pub first_fn: Option<Box<WithCall<T>>>,
pub second_fn: Option<Box<WithCall<T>>>,
}
fn main() {
let mut first_fn = WithCall::new(|| {
println!("Called!")
});
let mut second_fn = WithCall::new(|| {
println!("Called other!")
});
let has_with_call = HasWithCall {
first_fn: Some(Box::new(first_fn.clone())),
second_fn: Some(Box::new(second_fn.clone()))
};
println!("{:?}", first_fn.run());
let mut first_fn_a = first_fn.clone();
let mut first_fn_b = first_fn;
let a = thread::spawn(move || {
println!("In remote thread: {:?}", first_fn_a.run());
});
let b = thread::spawn(move || {
println!("In remote thread: {:?}", first_fn_b.run());
});
a.join().expect("Thread A panicked");
b.join().expect("Thread B panicked");
}
This code gives me the following error:
error[E0308]: mismatched types --> src/main.rs:39:34
second_fn: Some(Box::new(second_fn.clone()))
^^^^^^^^^^^^^^^^^ expected closure, found a different closure
note: expected type `WithCall<[closure@src/main.rs:29:38: 31:6]>`
found type `WithCall<[closure@src/main.rs:33:39: 35:6]>`
note: no two closures, even if identical, have the same type
help: consider boxing your closure and/or using it as a trait object
I've referenced this question for the thread-safe closures and this question for the closure type error.
I see that there are other options like a reference to a trait object or a function pointer. However, I'd like to solve this using a boxed trait object as I've written above.