Compiling playground v0.0.1 (/playground)
error[E0277]: `dyn std::ops::Fn() -> i32` cannot be shared between threads safely
--> src/main.rs:12:5
|
12 | thread::spawn(move || {
| ^^^^^^^^^^^^^ `dyn std::ops::Fn() -> i32` cannot be shared between threads safely
|
= help: the trait `std::marker::Sync` is not implemented for `dyn std::ops::Fn() -> i32`
= note: required because of the requirements on the impl of `std::marker::Send` for `&dyn std::ops::Fn() -> i32`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<&dyn std::ops::Fn() -> i32>`
= note: required because it appears within the type `[closure@src/main.rs:12:19: 15:6 f:std::sync::Arc<&dyn std::ops::Fn() -> i32>]`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground`.
To learn more, run the command again with --verbose.
You are using trait objects (i.e. the dyn Trait syntax), which forget everything about the contained type not explicitly specified. So if you want to send it to another thread, you must explicitly tell it not to forget that it may be sent to another thread. Additionally, don't put closures behind references.
So to make it compile, you need the type Arc<dyn Fn() -> i32 + Send + Sync>. playground
However you can also just not convert your closure to a trait object, in which case the compiler doesn't forget that your closure was thread-safe. That looks like this:
fn main() {
let x = 4;
let f = Arc::new(move || {
println!("ok {}", x);
3
});
thread::spawn(move || {
let f = Arc::clone(&f);
f();
});
}