Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

rust - Parameter type may not live long enough (with threads)

This is similar to Parameter type may not live long enough?, but my interpretation of the solution doesn't seem to be working. My original boiled-down test case is:

use std::fmt::Debug;
use std::thread;

trait HasFeet: Debug + Send + Sync + Clone {}

#[derive(Debug, Clone)]
struct Person;

impl HasFeet for Person {}

#[derive(Debug, Copy, Clone)]
struct Cordwainer<A: HasFeet> {
    shoes_for: A,
}

impl<A: HasFeet> Cordwainer<A> {
    fn make_shoes(&self) {
        let cloned = self.shoes_for.clone();
        thread::spawn(move || {
            println!("making shoes for = {:?}", cloned);
        });
    }
}

This gives me the error:

error[E0310]: the parameter type `A` may not live long enough
  --> src/main.rs:19:9
   |
16 | impl<A: HasFeet> Cordwainer<A> {
   |      -- help: consider adding an explicit lifetime bound `A: 'static`...
...
19 |         thread::spawn(move || {
   |         ^^^^^^^^^^^^^
   |
note: ...so that the type `[closure@src/main.rs:19:23: 21:10 cloned:A]` will meet its required lifetime bounds
  --> src/main.rs:19:9
   |
19 |         thread::spawn(move || {
   |         ^^^^^^^^^^^^^

Instead of making A 'static, I go through and add an explicit lifetime to the HasFeet trait:

use std::fmt::Debug;
use std::thread;

trait HasFeet<'a>: 'a + Send + Sync + Debug {}

#[derive(Debug, Copy, Clone)]
struct Person;

impl<'a> HasFeet<'a> for Person {}

struct Cordwainer<'a, A: HasFeet<'a>> {
    shoes_for: A,
}

impl<'a, A: HasFeet<'a>> Cordwainer<'a, A> {
    fn make_shoes(&self) {
        let cloned = self.shoes_for.clone();
        thread::spawn(move || {
            println!("making shoes for = {:?}", cloned);
        })
    }
}

This now gives me the error:

error[E0392]: parameter `'a` is never used
  --> src/main.rs:11:19
   |
11 | struct Cordwainer<'a, A: HasFeet<'a>> {
   |                   ^^ unused type parameter
   |
   = help: consider removing `'a` or using a marker such as `std::marker::PhantomData`

I think that 'a is used as the lifetime parameter to the HasFeet trait. What am I doing wrong here?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The std::thread::spawn() function is declared with a Send + 'static bound on its closure. Anything which this closure captures must satisfy the Send + 'static bound. There is no way around this in safe Rust. If you want to pass data to other threads using this function, it must be 'static, period.

It is possible to lift the 'static restriction with the proper API, see How can I pass a reference to a stack variable to a thread? for an example.

However, a 'static bound is not as scary as it may seem. First of all, you cannot force anything to do anything with lifetime bounds (you can't force anything to do anything with any kind of bounds). Bounds just limit the set of types which can be used for the bounded type parameter and that is all; if you tried to pass a value whose type does not satisfy these bounds, the compiler will fail to compile your program, it won't magically make the values "live longer".

Moreover, a 'static bound does not mean that the value must live for the duration of the program; it means that the value must not contain borrowed references with lifetimes other than 'static. In other words, it is a lower bound for possible references inside the value; if there are no references, then the bound does not matter. For example, String or Vec<u64> or i32 satisfy the 'static bound.

'static is a very natural restriction to put on spawn(). If it weren't present, the values transferred to another thread could contain references to the stack frame of the parent thread. If the parent thread finishes before the spawned thread, these references would become dangling.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...