2015-08-18 41 views
2

這與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 `[[email protected]/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

爲什麼你不想在產卵時用''static''生命週期來限制'A'?我非常肯定,你將不得不**,基於生成的線程可能超過父線程的事實。 [限制也非常非侵入性](http://is.gd/EjUX6Y)。 – Shepmaster

+0

我想我不確定在這種情況下''static'是什麼意思。我不想讓在'make_shoes'中使用的'A'被迫在程序期間強制生效。 – Watts

+0

它肯定不會泄露。基本上,你將把變量的所有權轉移給線程,並且該變量不允許有任何*引用*給那些無法保證在程序生命中活着的項目。 – Shepmaster

回答

8

std::thread::spawn()函數聲明爲在其閉包上綁定一個Send + 'static。這個封閉捕獲的任何東西都必須滿足Send + 'static的界限。在安全的Rust裏面有沒有。如果你想使用這個函數將數據傳遞給其他線程,它必須是'static,句點。

可以通過適當的API解除'static限制,例如參見How can I pass a reference to a stack variable to a thread?

但是,'static界限並不像看起來那麼可怕。首先,你不能用任何事物來做任何事情,只要有生命的邊界(你不能用任何東西來做任何事情)。邊界只是限制可用於有界類型參數的類型集合,即全部;如果你試圖傳遞一個類型不符合這些邊界的值,編譯器將無法編譯你的程序,它不會神奇地使這些值「活得更長」。

此外,'static界限並不意味着該值必須在程序期間存活;這意味着該值不得包含除'static以外的借用引用。換句話說,它是值內的可能引用的下界;如果沒有引用,那麼綁定無關緊要。例如,StringVec<u64>i32滿足'static界限。

'static是放在spawn()上的一個非常自然的限制。如果它不存在,則傳送到另一個線程的值可能包含對父線程堆棧幀的引用。如果父線程在生成的線程之前完成,則這些引用將變成懸空。

相關問題