error: lifetime may not live long enough

error - ライフタイムの不足』の再借用についての派生パターン。

背景情報

可変参照フィールドへのアクセスは、『再借用』により行われる。

そしてこの場合、結果の参照のライフタイムは、フィールドアクセス式のベース側のライフタイムにより制限される。そのため、フィールド側のライフタイムがたとえ長くても、ベース側のライフタイムが短いと、結果のライフタイムはベース側の短いものとなる。

パターン

パターン A

関数版

以下では、arg.0 は可変参照であるため、そのライフタイムは arg's になる。ここで、戻り値のライフタイムには 'l が期待されていて、arg の型から暗黙的に 'l: 's と分かる。そのため、ライフタイムが 's の参照は使えない。


struct Holder<'a>(&'a mut i32);

fn val<'l, 's>(arg: &'s Holder<'l>) -> &'l i32 {
    arg.0
}

error: lifetime may not live long enough
 --> src\lib.rs:5:5
  |
3 | fn val<'l, 's>(arg: &'s Holder<'l>) -> &'l i32 {
  |        --  -- lifetime `'s` defined here
  |        |
  |        lifetime `'l` defined here
4 |     arg.0
  |     ^^^^^ function was supposed to return data with lifetime `'l` but it is returning data with lifetime `'s`
  |
  = help: consider adding the following bound: `'s: 'l`

解決策 1

引数のライフタイムを長くする。


struct Holder<'a>(&'a mut i32);

fn val<'l>(arg: &'l Holder<'_>) -> &'l i32 {
    arg.0
}

解決策 2

戻り値のライフタイムを短くする。


struct Holder<'a>(&'a mut i32);

fn val<'l, 's>(arg: &'s Holder<'l>) -> &'s i32 {
    arg.0
}

パターン B

メソッド版

以下では、self.0 は可変参照であるため、そのライフタイムは self のそれと同じになる。ここで、戻り値のライフタイムには 'a が期待されていて、self のライフタイムは 'a より短い。そのため、ライフタイムが self と同じ参照は使えない。


struct Holder<'a>(&'a mut i32);

impl<'a> Holder<'a> {
    fn val(&self) -> &'a i32 {
        self.0
    }
}

error: lifetime may not live long enough
 --> src\lib.rs:5:9
  |
3 | impl<'a> Holder<'a> {
  |      -- lifetime `'a` defined here
4 |     fn val(&self) -> &'a i32 {
  |            - let's call the lifetime of this reference `'1`
5 |         self.0
  |         ^^^^^^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`

解決策 1

引数のライフタイムを長くする。


struct Holder<'a>(&'a mut i32);

impl<'a> Holder<'a> {
    fn val(&'a self) -> &'a i32 {
        self.0
    }
}

解決策 2

戻り値のライフタイムを短くする。


struct Holder<'a>(&'a mut i32);

impl Holder<'_> {
    fn val(&self) -> &i32 {
        self.0
    }
}