2017-08-23 143 views
3

最近,我這是通過簡單地改變'&self'和'&'a self'有什麼區別?

impl<'a> Foo<'a> { 
    fn foo(&'a self, path: &str) -> Boo<'a> { /* */ } 
} 

impl<'a> Foo<'a> { 
    fn foo(&self, path: &str) -> Boo { /* */ } 
} 

它並沒有按照我的理解是有意義解決的錯誤,因爲我認爲第二個版本是完全一樣的第一個應用了終生的elision。


在情況下,我們引入一個新的生存時間,這似乎是根據從nomicon這個例子的情況下的方法。

fn get_mut(&mut self) -> &mut T;      // elided 
fn get_mut<'a>(&'a mut self) -> &'a mut T;    // expanded 

那麼,這和我的第一個代碼被剪斷有什麼區別。

回答

4

終身'afn foo(&'a self, ...) ...定義爲impl<'a>,即所有foo調用都是相同的。

終生'afn get_mut<'a>(&'a mut self) ...是爲函數定義的。 get_mut的不同呼叫對於'a可以有不同的值。

您的代碼

impl<'a> Foo<'a> { 
    fn foo(&'a self, path: &str) -> Boo<'a> { /* */ } 
} 

不是消隱壽命的擴張。此代碼將借用期限&'a self與結構Foo<'a>的生命週期關聯起來。如果Foo<'a>'a不變,則self應保持借用,只要'a

消隱壽命的正確擴展是

impl<'a> Foo<'a> { 
    fn foo<'b>(&'b self, path: &str) -> Boo<'b> { /* */ } 
} 

此代碼不依賴於結構Foo的方差能夠借self較短壽命。

變體和不變結構之間差異的示例。

use std::cell::Cell; 

struct Variant<'a>(&'a u32); 

struct Invariant<'a>(Cell<&'a u32>); 

impl<'a> Variant<'a> { 
    fn foo(&'a self) -> &'a u32 { 
     self.0 
    } 
} 

impl<'a> Invariant<'a> { 
    fn foo(&'a self) -> &'a u32 { 
     self.0.get() 
    } 
} 

fn main() { 
    let val = 0; 
    let mut variant = Variant(&val);// variant: Variant<'long> 
    let mut invariant = Invariant(Cell::new(&val));// invariant: Invariant<'long> 
    { 
     let r = variant.foo(); 
     // Pseudocode to explain what happens here 
     // let r: &'short u32 = Variant::<'short>::foo(&'short variant); 
     // Borrow of `variant` ends here, as it was borrowed for `'short` lifetime 

     // Compiler can do this conversion, because `Variant<'long>` is 
     // subtype of Variant<'short> and `&T` is variant over `T` 
     // thus `variant` of type `Variant<'long>` can be passed into the function 
     // Variant::<'short>::foo(&'short Variant<'short>) 
    } 
    // variant is not borrowed here 
    variant = Variant(&val); 

    { 
     let r = invariant.foo(); 
     // compiler can't shorten lifetime of `Invariant` 
     // thus `invariant` is borrowed for `'long` lifetime 
    } 
    // Error. invariant is still borrowed here 
    //invariant = Invariant(Cell::new(&val)); 
} 

Playground link

+0

第二個變體告訴'噓<'b>'要活,只要借'和'B self'編譯器。那就是當'Boo <'b>'不再處於被採用的詞彙範圍時,'self'不再被借用。 – red75prime

+0

第一個變體將結構'Foo <'a>'的借用壽命和'自我'聯繫在一起。如果'Foo <'a>''[invariant](https://doc.rust-lang.org/nomicon/subtyping.html#variance)over''a',這意味着'self'應該保持借用,只要''了'。 – red75prime

+0

我加了一點解釋爲什麼'Foo'的變化會影響你的代碼。 – red75prime

相關問題