为什么编译器需要“静态生存期才能克隆然后移动”变量?

时间:2019-05-28 06:53:06

标签: rust

我在防锈寿命上有些挣扎: 为什么'static需要run_trait_test的生存期??

我希望它的行为像run_concrete_test

我阅读了文档,搜索了stackoverflow和锈皮书,但显然我遗漏了一些东西。

use std::thread;

#[derive(Debug, Clone)]
struct Test {
    test_string: String,
}

trait Example {
    fn tst(&self) -> ();
}

impl Example for Test {
    fn tst(&self) {
        println!("{:?}", self);
    }
}

// compiles, no 'static here
fn run_concrete_test(tester: &Test) {
    let t = tester.clone();
    thread::spawn(move || {
        t.tst();
    });
}

// compiles with 'static
// but F shouldn't be only static
fn run_trait_test<F>(tester: &'static F)
where
    F: Example + Sync + Send + 'static,
{
    let t = tester.clone();
    let store_t = thread::spawn(move || {
        t.tst();
    });
}

fn main() {
    //does run, no static
    let x = Test {
        test_string: "test string".to_string(),
    };
    run_concrete_test(&x);

    // doe sn't compile because of static
    // run_trait_test(&x);
    println!("{:?}", x);
}

1 个答案:

答案 0 :(得分:3)

From reference

  

所有&T都实现了以下特征,无论   所指对象的类型:

     
      
  • ...
  •   
  • 克隆(请注意,如果存在,这将不遵循T的Clone实现!)
  •   
  • ...
  •   

由于F具有'static边界,&F是一种共享变量:

  • 没有Clone的边界编译器将使用借来的clone F版本,只会返回借来的自我
  • Clone边界处,编译器将使用F的克隆实现,该克隆将返回F

使用上述所有代码,以下代码将与run_concrete_test相同:

fn run_trait_test<F>(tester: &F)
where
    F: Example + Sync + Send + Clone + 'static,
{
    let t = tester.clone();

    let store_t = thread::spawn(move || {
        t.tst();
    });
}

注意:在F没有'static边界的状态下,有可能F被视为某些T的边界借用的类型,例如F = &T

Playground