生存期間
2022/2/20 23:16:00
このエラーは、ある型に生存期間がないことを示します。関数シグネチャ内のエラーの場合、生存期間消去のルール(下記参照)を守らなかったことが問題である可能性があります。
エラーとなるコード例
struct Foo1 { x: &bool }.
// ^ 生存期間パラメータが期待される
struct Foo2<'a> { x: &'a bool }. // 正しい
struct Bar1 { x: Foo2}
// ^^^^ 生存期間パラメータが期待される
struct Bar2<'a> { x: Foo2<'a> } // 正しい
enum Baz1 { A(u8), B(&bool), }.
// ^ 生存期間パラメータが期待される
enum Baz2<'a> { A(u8), B(&'a bool), }. // 正しい
type MyStr1 = &str;
// ^ 生存期間パラメータが期待される
タイプ MyStr2<'a> = &'a str; // 正解
生存期間消去は、関数シグネチャの生存期間に関する特別で限定的な推論で、特定のケースで生存期間を省くことができる。
生存期間消去の背景については、[the book][book-le] を参照してください。
生存期間消去の規則では、出力生存期間が省略された関数署名は、以下のいずれかを持っていなければならないとされています。
&self
または &mut self
レシーバを持つメソッドであること。最初のケースでは、出力生存期間は一意の入力生存期間と同じであると推論される。2番目のケースでは、生存期間は &self
または &mut self
の生存期間と同じであると推論されます。
以下は消去エラーの例です。
// エラー, 入力生存期間がない
fn foo() -> &str { }.
// エラー, `x` と `y` の生存期間が異なることが推測される
fn bar(x: &str, y: &str) -> &str { }.
// error, `y` の生存期間は `x` の生存期間とは異なることが推測される。
fn baz<'a>(x: &'a str, y: &str) -> &str { }.
[book-le]: https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html#lifetime-elision
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
fn main() {
let str1 = String::from("long str");
let long_str;
{
let str2 = String::from("str");
long_str = longest(str1.as_str(), str2.as_str());
}
println!("long_str is {}", long_str); //long_str is long str
}
error[E0597]: `str2` does not live long enough
--> src\main.rs:14:43
|
14 | long_str = longest(str1.as_str(), str2.as_str());
| ^^^^^^^^^^^^^ borrowed value does not live long enough
15 | }
| - `str2` dropped here while still borrowed
16 | println!("long_str is {}", long_str); //long_str is long str
| -------- borrow later used here
For more information about this error, try `rustc --explain E0597`.
warning: `bollow` (bin "bollow") generated 1 warning
error: could not compile `bollow` due to previous error; 1 warning emitted
&'a
によってstr1とstr2が同じ生存期間だと示したにもかかわらず、生存期間が異なっているためにコンパイルエラーが生じる。
なので同じ生存期間(同じスコープ)にする必要がある。