error[E0597]: `x` does not live long enough

参照先が参照より先に破棄される場合に発生するエラー。

パターン

パターン A

スコープの違反

以下では、inside_valoutside_ref を比べると、前者が先に破棄される。
そのため、前者の参照は後者に代入できない。


fn main() {
    let outside_ref;

    {
        let inside_val = 0;
        outside_ref = &inside_val
    }

    dbg!(outside_ref);
}

error[E0597]: `inside_val` does not live long enough
 --> src\main.rs:6:23
  |
5 |         let inside_val = 0;
  |             ---------- binding `inside_val` declared here
6 |         outside_ref = &inside_val
  |                       ^^^^^^^^^^^ borrowed value does not live long enough
7 |     }
  |     - `inside_val` dropped here while still borrowed
8 |
9 |     dbg!(outside_ref);
  |          ----------- borrow later used here

パターン B

ライフタイムの違反

以下では、use_static_ref の引数は static ライフタイムの参照型でなければならない。
にも関わらず、ローカルライフタイムの参照 &local を指定している。


fn main() {
    let local = 0;
    use_static_ref(&local);
}

fn use_static_ref(_: &'static i32) {
    // NOP.
}

error[E0597]: `local` does not live long enough
 --> src\main.rs:3:20
  |
2 |     let local = 0;
  |         ----- binding `local` declared here
3 |     use_static_ref(&local);
  |     ---------------^^^^^^-
  |     |              |
  |     |              borrowed value does not live long enough
  |     argument requires that `local` is borrowed for `'static`
4 | }
  | - `local` dropped here while still borrowed

パターン C

Drop トレイトの影響 (兄弟フィールドの参照防止)

詳しくは『Drop トレイトのライフタイムへの影響 - 兄弟フィールドの参照防止』を参照。
(注: Drop トレイトを直接的に扱っていなくても考慮が必要。)

サンプル


fn main() {
    let mut data = MyData::default();
    data.on_drop = Some(OnDrop(&data.id));
}

#[derive(Default)]
struct MyData<'a> {
    id: i32,
    on_drop: Option<OnDrop<'a>>,
}

struct OnDrop<'a>(&'a i32);
impl<'a> Drop for OnDrop<'a> {
    fn drop(&mut self) {
        println!("ID [{}] is drpoped.", self.0)
    }
}

error[E0597]: `data.id` does not live long enough
 --> src\main.rs:3:38
  |
2 |     let mut data = MyData::default();
  |         -------- binding `data` declared here
3 |     data.on_drop = Some(OnDrop(&data.id));
  |                                ^^^^^^^^ borrowed value does not live long enough
4 | }
  | -
  | |
  | `data.id` dropped here while still borrowed
  | borrow might be used here, when `data` is dropped and runs the destructor for type `MyData<'_>`

パターン D (改良済)

Drop トレイトの影響 (ブロック式の末尾)
[旧情報]

詳しくは『Drop トレイトのライフタイムへの影響 - ブロック式の末尾処理』を参照。
(注: Drop トレイトを直接的に扱っていなくても考慮が必要。)

サンプル

以下では、OnDrop(&local) がブロック式の末尾にある。しかし、その破棄による drop が実行される時点で、local はすでに破棄され使えなくなっている。


fn main() {
    let val = {
        let local = 42;
        *OnDrop(&local).0
    };

    println!("{}", val);
}

struct OnDrop<'a>(&'a i32);
impl Drop for OnDrop<'_> {
    fn drop(&mut self) {
        println!("ID [{}] is drpoped.", self.0)
    }
}

error[E0597]: `local` does not live long enough
 --> src\main.rs:4:11
  |
3 |         let local = 42;
  |             ----- binding `local` declared here
4 |         *OnDrop(&local).0
  |          -------^^^^^^-
  |          |      |
  |          |      borrowed value does not live long enough
  |          a temporary with access to the borrow is created here ...
5 |     };
  |     -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `OnDrop`
  |     |
  |     `local` dropped here while still borrowed
  |
  = note: the temporary is part of an expression at the end of a block;
          consider forcing this temporary to be dropped sooner, before the block's local variables are dropped
help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block
  |
4 |         let x = *OnDrop(&local).0; x
  |         +++++++                  +++

パターン E

HRTB の機能制限

note: due to current limitations in the borrow checker, this implies a `'static` lifetime

このパターンはエラーメッセージに上記の特徴的な注釈が含まれる。

詳しくは『E0597 - HRTB の機能制限』を参照。