Perl日記

日々の知ったことのメモなどです。Perlは最近やってないです。

Rust で関数から trim した &str を返したかった

以下はコンパイルエラーになる。

fn main() {
    let foo = foo();
    println!("{}", foo);
}

fn foo() -> &str {
    let m = String::from("aiueo");
    m.trim()
}
error[E0106]: missing lifetime specifier
 --> src\main.rs:6:13
  |
6 | fn foo() -> &str {
  |             ^ expected named lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
  |
6 | fn foo() -> &'static str {
  |             ~~~~~~~~

For more information about this error, try `rustc --explain E0106`.
error: could not compile zzz due to previous error
  • trim() の返り値はメソッド元の文字列(所有者)のスライスになっている
  • foo() 内の変数 m(所有者)は、foo() から main() に戻るときにスコープから外れるので消滅する
  • 返すスライス(文字列)本体が消滅したので返せなくてエラーになる

すなわち、エラーメッセージの

this function's return type contains a borrowed value, but there is no value for it to be borrowed from

ということ。

学習中のいまの自分の解決策は、String を返すしかわからなかった。
これなら関数の境界を超える際に String オブジェクトの所有権の移動が行われるので、実際の値は破棄されない。

fn main() {
    let foo = foo();
    println!("{}", foo);
}

fn foo() -> String {
    let m = String::from("aiueo");
    m.trim().to_string()
}
補足メモ

The Rust Programming Language の例で、
スライス型 - The Rust Programming Language 日本語版

fn first_word(s: &String) -> &str {
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }

    &s[..]
}

があり、文字列スライスを返していてあれ?、と思ったが、返却は引数の s のスライスで、関数使用の引数に借用を使用していて、引数の s の所有権はそもそも移動しておらず、リターン時のスコープから外れたことによる消滅は発生しないのであった。