Yes. There are several problems with your code.
First of all, FnOnce is a sign, so you cannot use it directly. Traits should be either a restriction on a particular type, or for any indirectness. Since you are sending the closure to another place, you need something like Box<FnOnce(...)> .
Secondly, you cannot use Box<FnOnce(...)> because, due to object security rules, you cannot actually call FnOnce through indirect binding.
(As an aside, you also don't want to use the FnOnce<...> syntax, which is technically unstable, use FnOnce(...) instead.)
To solve this problem, you can switch to Fn or FnMut or use the not yet stable FnBox feature. I took this path on the grounds that it probably has the semantics you want and is likely to be stabilized in the near future. If you are not comfortable, you need to change your closure accordingly.
The following is a collaborative effort between me and the Manisher (who indicated that I missed the + Send constraint):
// NOTE: Requires a nightly compiler, as of Rust 1.0. #![feature(core)] use std::boxed::FnBox; use std::thread; use std::sync::mpsc; #[derive(Debug)] struct Test { s1: String, s2: String, } type ClosureType = Box<FnBox(&mut Test) + Send>; fn main() { let t = Test { s1: "Hello".to_string(), s2: "Hello".to_string() }; let (tx, rx) = mpsc::channel::<ClosureType>(); thread::spawn(move || { let mut test = t; let f = rx.recv().unwrap(); f.call_box((&mut test,)); println!("{:?}", test); }); tx.send(Box::new(move |t: &mut Test| { let s = "test".to_string(); t.s1 = s; })).unwrap(); // To give the output time to show up: thread::sleep_ms(100); }
DK.
source share