Rust - str が引数/戻り値で使えない理由
What it means is harder to explain succinctly. Rust has a number of types that are unsized. The most prevalent ones are str and [T]. Contrast these types to how you normally see them used: &str or &[T]. You might even see them as Box<str> or Arc<[T]>. The commonality is that they are always used behind a reference of some kind.
Because these types don't have a size, they cannot be stored in a variable on the stack — the compiler wouldn't know how much stack space to reserve for them! That's the essence of the error message.
まずはエラーメッセージそのもの、「the size for values of type str cannot be known at compilation time」について
str を &'static str にすれば解決します。 Rustでは勝手にポインタが作られたりしないので str は任意長の文字列そのものを表わします。これを関数から返すということは、例えば1000文字の文字列ならば1000文字分のデータをコピーして呼出元に返すことになります。今のところRustは任意長のデータをスタックにコピーする操作は許していません。そこで &str とポインタを介すると16バイト(ポインタサイズ8バイト+strのサイズ8バイト)と定サイズになるのでエラーにならなくなります。
「str 型を生で使うことはない」と覚えてしまっていいでしょう。
str は任意長の文字列そのものを表わします[1]
今のところRustは任意長のデータをスタックにコピーする操作は許していません[2]
この2点を前提とすれば、以下のように説明できるだろうか。
str
は任意帳の文字列そのものを表す、すなわち
[0] -> 'H'
[1] -> 'e'
[2] -> 'l'
[3] -> 'l'
[4] -> 'o'
の構造で表される「文字のリスト」としての文字列そのものである。
関数の引数として渡された値は、スタックへ乗せられる[3]。しかし、スタックへ載せられるデータは全て既知の固定サイズである → 任意長のデータはスタックへは乗せられない(ヒープに乗せなくてはならない)ので、 str
を引数として使うことはできない。よって、コンパイルエラーとなる。
また、関数の戻り値もやはりスタックへ乗せられる[4]ので、戻り値もやはり既知の固定サイズでなくてはならず、任意長のデータである str
は利用できない。
代わりに &str
として str
への参照を、すなわちポインタを使えばそれは固定値となる[5]ので、コンパイルエラーにならない。
-
https://doc.rust-jp.rs/book-ja/ch08-02-strings.html#文字列でutf-8でエンコードされたテキストを保持する "Rustには、言語の核として1種類しか文字列型が存在しません。 文字列スライスのstrで、通常借用された形態&strで見かけます。" ↩︎
-
https://doc.rust-jp.rs/book-ja/ch04-01-what-is-ownership.html "スタックを高速にする特性は他にもあり、それはスタック上のデータは全て既知の固定サイズでなければならないということです。" ↩︎
-
https://doc.rust-jp.rs/book-ja/ch04-01-what-is-ownership.html
"コードが関数を呼び出すと、関数に渡された値(ヒープのデータへのポインタも含まれる可能性あり)と、 関数のローカル変数がスタックに載ります。関数の実行が終了すると、それらの値はスタックから取り除かれます。" ↩︎ -
https://brain.cc.kogakuin.ac.jp/~kanamaru/lecture/MP/final/part06/node9.html "square 関数が終了するとスタック領域は図 7(c) のようになり、 戻り値 $v0 の値が変数 b に代入されてプログラムが終了する。" ↩︎
-
https://ja.stackoverflow.com/questions/65708/rustのresultについての質問-errore0277-the-size-for-values-of-type-str-cannot-be-kno "そこで &str とポインタを介すると16バイト(ポインタサイズ8バイト+strのサイズ8バイト)と定サイズになるのでエラーにならなくなります。" ↩︎