2017-08-23 3 views
3

私は最近、単に私の理解によると意味がありませんでした'&self'と '&' a selfの違いは何ですか?私は2番目のバージョンは正確に同じであることを考えたよう

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

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

を変更することで解決したエラーが発生しました適用された寿命エリシジョンを有する最初のものである。場合


我々は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の呼び出しで同じです。

fn get_mut<'a>(&'a mut self) ...の寿命'aが定義されています。 get_mutの異なるコールは、'aの異なる値を持つことができます。

あなたのコード

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

は省略さ寿命の拡張ではありません。このコードは、&'a selfの借用期間と構造Foo<'a>の有効期間を結びつけています。 Foo<'a>'aを超えて不変の場合、selfは、'aの間だけ借用したままにしてください。省略さ寿命の

正しい展開は、このコードは短い寿命のためselfを借りることができるように構造Fooの分散に依存しない

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

です。

バリアント構造と不変構造の違いの例。

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>'が 'a 'を介して[invariant](https://doc.rust-lang.org/nomicon/subtyping.html#variance)である場合、それは' 'self''が' '' a'。 – red75prime

+0

'Foo'の分散があなたのコードに及ぼす影響を少し説明しました。 – red75prime

関連する問題