title: Can a Rust closure be used by multiple threads?
body: <p>I'd like the ability to have multiple threads evaluate the same closure. The application I have in mind is parallelized numerical integration, so a situation where the function domain can be easily split into N chunks and handed to threads.</p>
  
  <p>This is a simple function that evaluates the provided closure multiple times and averages the result:</p>
  
  <pre><code>use std::sync::mpsc;
  use std::thread;
  
  const THREAD_COUNT: u64 = 4;
  
  fn average&lt;F: Fn(f64) -&gt; f64&gt;(f: F) -&gt; f64 {
      let (tx, rx) = mpsc::channel();
      for id in 0..THREAD_COUNT {
          let thread_tx = tx.clone();
          thread::spawn(move || {
              thread_tx.send(f(id as f64));
          });
      }
  
      let mut total = 0.0;
      for id in 0..THREAD_COUNT {
          total += rx.recv().unwrap();
      }
      total / THREAD_COUNT as f64
  }
  
  fn main() {
      average(|x: f64| -&gt; f64 { x });
  }
  </code></pre>
  
  <p>When I compile I get this error:</p>
  
  <pre class="lang-none prettyprint-override"><code>error[E0277]: `F` cannot be sent between threads safely
    --&gt; src/main.rs:10:9
     |
  10 |         thread::spawn(move || {
     |         ^^^^^^^^^^^^^ `F` cannot be sent between threads safely
     |
     = help: within `[closure@src/main.rs:10:23: 12:10 thread_tx:std::sync::mpsc::Sender&lt;f64&gt;, f:F, id:u64]`, the trait `std::marker::Send` is not implemented for `F`
     = help: consider adding a `where F: std::marker::Send` bound
     = note: required because it appears within the type `[closure@src/main.rs:10:23: 12:10 thread_tx:std::sync::mpsc::Sender&lt;f64&gt;, f:F, id:u64]`
     = note: required by `std::thread::spawn`
  </code></pre>
  
  <p>So I add <code>+ Send</code> to the bounds on <code>F</code> and get a new error:</p>
  
  <pre class="lang-none prettyprint-override"><code>error[E0310]: the parameter type `F` may not live long enough
    --&gt; src/main.rs:10:9
     |
  6  | fn average&lt;F: Fn(f64) -&gt; f64 + Send&gt;(f: F) -&gt; f64 {
     |            -- help: consider adding an explicit lifetime bound `F: 'static`...
  ...
  10 |         thread::spawn(move || {
     |         ^^^^^^^^^^^^^
     |
  note: ...so that the type `[closure@src/main.rs:10:23: 12:10 thread_tx:std::sync::mpsc::Sender&lt;f64&gt;, f:F, id:u64]` will meet its required lifetime bounds
    --&gt; src/main.rs:10:9
     |
  10 |         thread::spawn(move || {
     |         ^^^^^^^^^^^^^
  </code></pre>
  
  <p>So I add <code>+ 'static</code> to <code>F</code> and get this:</p>
  
  <pre class="lang-none prettyprint-override"><code>error[E0382]: capture of moved value: `f`
    --&gt; src/main.rs:11:28
     |
  10 |         thread::spawn(move || {
     |                       ------- value moved (into closure) here
  11 |             thread_tx.send(f(id as f64));
     |                            ^ value captured here after move
     |
     = note: move occurs because `f` has type `F`, which does not implement the `Copy` trait
  </code></pre>
  
  <p>So I add <code>+ Copy</code> to <code>F</code> and get:</p>
  
  <pre class="lang-none prettyprint-override"><code>error: the trait `core::marker::Copy` is not implemented for the type `[closure@src/test.rs:115:11: 115:26]
  </code></pre>
  
  <p>It seems every thread wants its own copy of the closure (because of <code>move</code>) but closures don't implement <code>Copy</code> so no luck. It seems strange to me because if the closures are never mutating state then what's the safety issue with multiple threads accessing them?</p>
  
  <p>I can get the code to work by providing a regular function instead of a closure, but this makes my code non-generic, i.e. it only works for a specific function instead of for anything that's <code>Fn(f64) -&gt; f64</code>. And for the type of integration I'm doing, the functions integrated often have certain fixed variables mixed with the variable of integration, so it would seem natural to capture the fixed variables with a closure.</p>
  
  <p>Is there some way to make this kind of multithreaded function evaluation work in a generic manner? Am I just thinking about things wrong?</p>