参数类型可能不够长(带线程)

时间:2015-08-18 22:41:40

标签: rust

这类似于Parameter type may not live long enough?,但我对解决方案的解释似乎并不奏效。我最初的煮沸测试用例是:

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);
        });
    }
}

这给了我错误:

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 || {
   |         ^^^^^^^^^^^^^

我没有进行A 'static,而是为HasFeet特征添加明确的生命周期:

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);
        })
    }
}

现在这给了我错误:

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`

我认为'a用作HasFeet特征的生命周期参数。我在这里做错了什么?

1 个答案:

答案 0 :(得分:12)

std::thread::spawn()函数声明其闭包时绑定了$Object = []; foreach($array as $key => $val){ $Object[$key] = (object)$val; } print_r($Object); 。此闭包捕获的任何内容都必须满足Send + 'static边界。在安全的Rust中有 no 方法。如果要使用此函数将数据传递给其他线程,则必须为Send + 'static,句点。

可以使用正确的API解除'static限制,有关示例,请参阅How can I pass a reference to a stack variable to a thread?

然而,'static界限并不像看起来那么可怕。首先,你不能强制任何东西做任何有生命界限的事情(你不能强制任何东西对任何类型的界限做任何事情)。 Bounds只是限制了可以用于有界类型参数的类型集合,这就是全部;如果你试图传递一个类型不满足这些边界的值,编译器将无法编译你的程序,它不会神奇地使值“活得更久”。

此外,'static约束并不意味着该值必须在程序期间存在;这意味着该值不得包含带有'static以外生命周期的借用引用。换句话说,它是值内可能引用的下限;如果没有引用,则绑定无关紧要。例如,'staticStringVec<u64>符合i32边界。

'static是一个非常自然的限制,可以放在'static上。如果它不存在,则传递给另一个线程的值可能包含对父线程的堆栈帧的引用。如果父线程在生成的线程之前完成,则这些引用将变为悬空。