🦀

RustでString型から&'static str型に変更することはできない

2022/08/24に公開

発端

以下のサイトでString型から&str型への変換はlet ss: &str = &s[..];みたいな感じでできると書いてあったが、なんかおかしくないか?と思ったのが始まり
[Rust] 文字列 String から文字列スライス str へ変換される仕組み

二つの比較コード

例えば、以下のようなコードを考える

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

fn dangle() -> &'static str {
    let s =  String::from("hello");
    let ss:&str = &s;
    ss
}

上記はssが借用したものとしてエラーになる

error[E0515]: cannot return value referencing local variable `s`
 --> prog.rs:9:5
  |
8 |     let ss:&str = &s;
  |                   -- `s` is borrowed here
9 |     ss
  |     ^^ returns a value referencing data owned by the current function

error: aborting due to previous error

For more information about this error, try `rustc --explain E0515`.

一方で以下はエラーにはならない

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

fn dangle() -> &'static str {
    let s: &str =  "hello";
    s
}

もし、let ss:&str = &s;が&strへの変換になるならば、どちらも正常に動作しないとおかしい気がした。

String自体のライフタイムの制約が変換後の&strにも適応されるためstaticにならない。

調べたらstackoverflowで回答があった
How to convert a String into a &'static str

You cannot obtain &'static str from a String because Strings may not live for the entire life of your program, and that's what &'static lifetime means. You can only get a slice parameterized by String own lifetime from it.

&'static str をStringから取得することはできません。これは、Stringがプログラムの存続期間全体にわたって存在しない可能性があるためです。これが、&'static の有効期間の意味です。 String 自身のライフタイムによってパラメーター化されたスライスのみを取得できます。

Stringを&strに変換したものはStringのライフタイムに縛られるということである。
String型はstaticなライフタイムを指定できないので、Stringから&strに変換したものはstaticなライフタイムは持つことは無いことになる。
これが、前のセクションで述べたプログラムがエラーになった原因である。

そのため、let ss:&str = &s;が&strへの変換というのは間違いではないが、全く同じものになるというわけでは無いらしい。

Discussion