Given
fn greet(peeps: &str) {
println!("Hello, {}", peeps);
}
I can do:
fn main() {
let a = "World";
thread::spawn(move || greet(a)).join().unwrap();
}
The compiler understands that the thread does not outlive the borrowed string, but this is merely a special case when the lifetime of the &str
is known to be 'static
. When I try to do the same with a function argument, it does not compile:
fn indirect(peeps: &str) {
thread::spawn(move || greet(&peeps)).join().unwrap();
// Does not compile, for fear that the thread may outlive peeps
}
However, to a human reader, it is obviously the case that the thread cannot outlive the borrowed string.
I have found two workarounds:
Make a copy of the string, which can be moved into the thread:
fn indirect(peeps: &str) { let peeps = peeps.to_string(); thread::spawn(move || greet(&peeps)).join().unwrap(); }
or, make use of the famously deprecated
thread::scoped
:#![feature(scoped)] fn indirect_scoped(peeps: &str) { thread::scoped(move || greet(&peeps)).join(); }
I don't want to specify 'static
lifetime for the function parameter, I'd prefer not to make an unnecessary copy (workaround 1) and I'd prefer not to use deprecated features (workaround 2).
What should I do in this situation?
Arc<String>
could also be a solution to this problem. It would require callingto_string()
at some point given a&str
, but then it could be shared across many threads without copying. – BurntSushi5scoped
will come back into the standard library. – sellibitze