2017-08-23 113 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

相关问题