2017-09-26 44 views
1

我有一個生命期的問題CellUnsafeCell/RefCell/...)引用。從我的理解這個代碼應編譯:爲什麼'細胞'是特別爲借用檢查?

fn test1<'a, 'b: 'a>(x: Cell<&'b u32>) { 
    let x2: Cell<&'a u32> = x; 
} 

但它會產生一個錯誤:

error[E0308]: mismatched types 
--> src/main.rs:4:29 
    | 
4 |  let x2: Cell<&'a u32> = x; 
    |       ^lifetime mismatch 
    | 
    = note: expected type `std::cell::Cell<&'a u32>` 
      found type `std::cell::Cell<&'b u32>` 
note: the lifetime 'a as defined on the function body at 3:1... 
--> src/main.rs:3:1 
    | 
3 |/fn test1<'a, 'b: 'a>(x: Cell<&'b u32>) { 
4 | |  let x2: Cell<&'a u32> = x; 
5 | | } 
    | |_^ 
note: ...does not necessarily outlive the lifetime 'b as defined on the function body at 3:1 
--> src/main.rs:3:1 
    | 
3 |/fn test1<'a, 'b: 'a>(x: Cell<&'b u32>) { 
4 | |  let x2: Cell<&'a u32> = x; 
5 | | } 
    | |_^ 

我覺得:<>是並不知名的運營商,但我發現它在一些RFC試圖解決的時候我的問題。

我應該可以做出一個更短的生命週期的Cell更長。當我用一些虛擬包裝替換Cell類型時,一切正常,所以從我的實驗中看來,CellUnsafeCell等)在處理參考生命期時被特別對待。

這不是我原來的問題。我想在多個結構之間有一些共享狀態 - 一個主結構與RefCell和子結構參考RefCell,但是我不能在借用自己的情況下獲得借閱檢查器,而無需藉助整個對象的生命。請參閱:

struct A<'a> { 
    x: RefCell<&'a u32>, 
} 

impl<'a> A<'a> { 
    fn new(x: &'a u32) -> A<'a> { 
     A { x: RefCell::new(x) } 
    } 

    fn foo(&self) -> B<'a> { 
     B { x: &self.x } 
    } 
} 

struct B<'a> { 
    x: &'a RefCell<&'a u32>, 
} 

如果我在foo添加一生'aself,它編譯但隨後失敗,此代碼:

let fs = A::new(&x); 
{ 
    fs.foo(); 
} 
let fs2 = fs; 

錯誤:錯誤[E0505]:不能搬出fs,因爲它是借用

是否有其他方法來實現對象之間的共享狀態?我正在使用單線程,所以現在沒有同步問題。

+1

見https://doc.rust-lang.org/nomicon/subtyping.html用於解釋爲什麼它會是不安全的,讓'細胞'在存儲類型上是變體。 – interjay

+1

總而言之:'Cell '在'T'上是不變的,因爲'Cell'可以在存儲在'&'-ref中時發生變異,並且允許變異意味着您可以在'Cell'中存儲具有更短生命週期的引用('let x2:&Cell <&'a u32> =&x; x2.set(somethingWithLifetimeA); x.get()//返回&'b T真的只爲'a'生活) –

+0

謝謝你指點我的材料和提供的例子差異如何工作!這幫助我瞭解先生。借用檢查器併爲我的問題提出解決方案。沒想到能很快找到解決方案:) – Rafalh

回答

3

正如評論中所述,我的問題是由Cell type invariance造成的。我設法通過使用兩個生命週期來解決我的原始問題,而不是在任何地方使用同一生命。現在&selffoo借用一個短的壽命比'a

struct A<'a> { 
    x: RefCell<&'a u32>, 
} 

impl <'a> A<'a> { 
    fn new(x: &'a u32) -> A<'a> { 
     A { 
      x: RefCell::new(x), 
     } 
    } 

    fn foo<'b>(&'b self) -> B<'b, 'a> { 
     B { 
      x: &self.x, 
     } 
    } 
} 

struct B<'b, 'a: 'b> { 
    x: &'b RefCell<&'a u32>, 
} 
相關問題