error[E0716]: temporary value dropped while borrowed

参照中に中間値が破棄された。

パターン

パターン A

基本形

殆どの場合、式内の中間値の破棄は、文末 (セミコロンの位置) にて行われる。

そのため、それ以降にその中間値に由来する参照を使用するとエラーになる。

サンプル

以下では、式内の中間値 Foo::new() から、メソッド val_ref() で参照をたどり、その結果を変数 ref_to_temp へと保存して利用している。しかし、ref_to_temp へと値を保存する文の文末にてすでに参照先の中間値は破棄されてしまっている。


fn main() {
    let ref_to_temp = Foo::new().val_ref();
    println!("Value is {}.", *ref_to_temp);
}

struct Foo {
    val: i32
}

impl Foo {
    fn new() -> Self {
        Self { val: 0 }
    }
    
    fn val_ref(&self) -> &i32 {
        &self.val
    }
}

error[E0716]: temporary value dropped while borrowed
 --> src\main.rs:2:21
  |
2 |     let ref_to_temp = Foo::new().val_ref();
  |                       ^^^^^^^^^^          - temporary value is freed at the end of this statement
  |                       |
  |                       creates a temporary value which is freed while still in use
3 |     println!("Value is {}.", *ref_to_temp);
  |                              ------------ borrow later used here
  |
help: consider using a `let` binding to create a longer lived value
  |
2 ~     let binding = Foo::new();
3 ~     let ref_to_temp = binding.val_ref();

解決策

エラーメッセージの help にある通り、中間値をローカル変数に保存する。

パターン B

借用式

借用式 (&x) の演算対象 (x) がアドレスでなく通常の値の場合、必要に応じて現在のスコープに値が自動保存され、式の結果はそこへの参照となる。そのためこの場合、中間値を生成した文より後でも、スコープ内ならばその中間値への参照を使える。

つまり、借用式では中間値と参照まわりのエラーはあまり起きない。ただそれでも、中間値の参照を静的参照として利用したりすると、やはりエラーになる。

サンプル

以下では、借用式内の中間値 Foo::new() のフィールド val への参照が、変数 ref_to_temp から参照できるよう、中間値が自動保存されている。しかし、その中間値は静的に保存されているわけではない。そのため、ref_to_temp は、関数 use_ref の引数にはなれない。


fn main() {
    let ref_to_temp = &Foo::new().val;
    use_ref(ref_to_temp);
}

fn use_ref(arg: &'static i32) {
    println!("Value is {}.", *arg);
}

struct Foo {
    val: i32
}

impl Foo {
    fn new() -> Self {
        Self { val: 0 }
    }
}

error[E0716]: temporary value dropped while borrowed
 --> src\main.rs:2:24
  |
2 |     let ref_to_temp = &Foo::new().val;
  |                        ^^^^^^^^^^ creates a temporary value which is freed while still in use
3 |     use_ref(ref_to_temp);
  |     -------------------- argument requires that borrow lasts for `'static`
4 | }
  | - temporary value is freed at the end of this statement