生涯'a
のfn 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
第二の変形は 'ブー<'b>は'借り '& 'のb self'限り生きなければならないことをコンパイラに伝えます。つまり、 'Boo <'b>'はレキシカルスコープになっていないので、 'self'はもう借用されません。 – red75prime
最初の変種は、構造体 'Foo <'a>'の生涯に ''自己 'の借用の生涯を結びつけます。 'Foo <'a>'が 'a 'を介して[invariant](https://doc.rust-lang.org/nomicon/subtyping.html#variance)である場合、それは' 'self''が' '' a'。 – red75prime
'Foo'の分散があなたのコードに及ぼす影響を少し説明しました。 – red75prime