error[E0716]: temporary value dropped while borrowed
一時的な値が参照中に破棄された。
殆どの場合、式内の一時的な値は、文末 (セミコロンの位置) で破棄される。
そのため、それ以降にそれに由来する参照を使用するとエラーになる。
以下では、一時的な値 Foo::new()
の参照を val_ref()
でたどり、結果を 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
にある通り、一時的な値をローカル変数に保存する。
参照式 (&x
) は必要に応じて現在のスコープに演算対象 (x
) を保存する。そのため、一時的な値に由来する参照でも、この場合は基本形のパターンとは異なり、その参照がすぐに使えなくなる事はない。ただし、スコープを超えた利用ではやはりエラーになる。
以下では、参照式により一時的な値に由来する Foo::new().val
がスコープに保存される。そのため、それを参照する ref_to_temp
の使用は妥当である。しかし、関数 use_ref
の引数のライフタイムは 'static
であるため、その保存期間を超えてしまっている。
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
Drop
トレイトの影響
詳しくは『Drop トレイトのライフタイムへの影響 - ライフタイムの延長』を参照。
(注: Drop
トレイトを直接的に扱っていなくても考慮が必要。)
このパターンは変数をバインドだけして使用しないレアケースで発生する。
変数を使用すると、基本形のパターンのメッセージに変わる。
_var
を使用すると基本形のパターンのメッセージに変わる
fn main() {
let _var = temp().my_ref();
}
fn temp() -> MyType {
MyType(0)
}
struct MyType(i32);
impl MyType {
pub fn my_ref(&self) -> MyRef<'_> {
MyRef(&self.0)
}
}
struct MyRef<'a>(&'a i32);
impl Drop for MyRef<'_> {
fn drop(&mut self) {
println!("ID [{}] is drpoped.", self.0)
}
}
error[E0716]: temporary value dropped while borrowed --> src\main.rs:2:16 | 2 | let _var = temp().my_ref(); | ^^^^^^ - temporary value is freed at the end of this statement | | | creates a temporary value which is freed while still in use 3 | } | - borrow might be used here, when `_var` is dropped and runs the `Drop` code for type `MyRef` | help: consider using a `let` binding to create a longer lived value | 2 ~ let binding = temp(); 3 ~ let _var = binding.my_ref(); |