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 の所有権はそもそも移動しておらず、リターン時のスコープから外れたことによる消滅は発生しないのであった。