t_wの輪郭

&'

2022/2/20 23:16:00

あれ

2022/2/20 23:45:00
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

fn main() {
    let str1 = "str";
    let str2 = "long str";
    let long_str = longest(str1, str2);
    println!("long_str is {}", long_str);   //long_str is long str
}

missing lifetime specifier

2022/2/20 23:34:00
fn longest(x: &str, y: &str) -> &str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

fn main() {
    let str1 = "str1";
    let str2 = "str2 hogehoge";
    let long = longest(&x, &y);
}
error[E0106]: missing lifetime specifier
 --> src\main.rs:1:33
  |
1 | fn longest(x: &str, y: &str) -> &str {
  |               ----     ----     ^ expected named lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
help: consider introducing a named lifetime parameter
  |
1 | fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
  |           ++++     ++          ++          ++

このエラーは、ある型に生存期間がないことを示します。関数シグネチャ内のエラーの場合、生存期間消去のルール(下記参照)を守らなかったことが問題である可能性があります。

エラーとなるコード例

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] を参照してください。

生存期間消去の規則では、出力生存期間が省略された関数署名は、以下のいずれかを持っていなければならないとされています。

  • ちょうど1つの入力生存期間
  • または、複数の入力生存期間があるが、その関数が &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

does not live long enough

2022/2/20 23:56:00
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が同じ生存期間だと示したにもかかわらず、生存期間が異なっているためにコンパイルエラーが生じる。
なので同じ生存期間(同じスコープ)にする必要がある。