Generic fn, channel, and thread spawn

186 views Asked by At

I have this code here: (Playground link)

use std::thread;
use std::sync::mpsc::channel;

fn run<T: Send>(task: fn() -> T) -> T {
    let (tx, rx) = channel();
    thread::spawn(move || {
        tx.send(task());
    });
    rx.recv().unwrap()
}

fn main() {
    let task = || 1 + 2;

    let result = run(task);

    println!("{}", result);
}

But I'm getting a lifetime error I can't figure out.

<anon>:6:5: 6:18 error: the parameter type `T` may not live long enough [E0310]
<anon>:6     thread::spawn(move || {
             ^~~~~~~~~~~~~
<anon>:6:5: 6:18 help: consider adding an explicit lifetime bound `T: 'static`...
<anon>:6:5: 6:18 note: ...so that captured variable `tx` does not outlive the enclosing closure
<anon>:6     thread::spawn(move || {
             ^~~~~~~~~~~~~
<anon>:15:22: 15:26 error: mismatched types:
 expected `fn() -> _`,
    found `[closure <anon>:13:16: 13:24]`
(expected fn pointer,
    found closure) [E0308]
<anon>:15     let result = run(task);
                               ^~~~

Any suggestions? Thanks!

1

There are 1 answers

2
mbrubeck On BEST ANSWER

The error message suggests adding a 'static bound to the type parameter T. If you do this, it will get rid of the first error:

fn run<T: Send + 'static>(task: fn() -> T) -> T

The 'static bound is needed to guarantee that the value returned by task can outlive the function where task runs. Read more about the 'static lifetime.

The second error is that you are passing a closure, while run expects a function pointer. One way to fix this is by changing task from a closure to a fn:

    fn task() -> u32 { 1 + 2 }

Here's the complete working code:

use std::thread;
use std::sync::mpsc::channel;

fn run<T: Send + 'static>(task: fn() -> T) -> T {
    let (tx, rx) = channel();
    thread::spawn(move || {
        tx.send(task());
    });
    rx.recv().unwrap()
}

fn main() {
    fn task() -> u32 { 1 + 2 }
    let result = run(task);
    println!("{}", result);
}