Reputation: 544
I struggle a little with rust lifetimes:
why is 'static
lifetime needed for run_trait_test
?.
I want it to behave like run_concrete_test
I read the documentation, searched stackoverflow and the rust-book but I'm obviously missing something.
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);
}
Upvotes: 3
Views: 1734
Reputation: 8793
The following traits are implemented for all &T, regardless of the type of its referent:
- ...
- Clone (Note that this will not defer to T's Clone implementation if it exists!)
- ...
Since F
has 'static
lifetime boundary, &F
is a type of shared variable:
Clone
boundary compiler will use clone
from borrowed
version of F
(Simply it would just clone the reference)Clone
boundary, compiler will use the implementation of F
's Clone
With all of these the code below will work as same with run_concrete_test
:
trait Example {
fn test(&self);
}
fn _run_trait_test<F>(tester: &F)
where
F: Example + Sync + Send + Clone + 'static,
{
let t = tester.clone();
::std::thread::spawn(move || {
t.test();
});
}
Note: Without 'static
lifetime boundary it is possible that F
could be considered as some T
's borrowed type like F = &T
Upvotes: 4