web-dev-qa-db-ja.com

「strはコンパイル時に既知の一定のサイズを持たない」とはどういう意味ですか、それを修正する最も簡単な方法は何ですか?

関数パラメーターから派生した文字列を操作して、その操作の結果を返そうとしています:

fn main() {
    let a: [u8; 3] = [0, 1, 2]; 
    for i in a.iter() {
        println!("{}", choose("abc", *i));
    }
}

fn choose(s: &str, pad: u8) -> String {
    let c = match pad {
        0 => ["000000000000000", s].join("")[s.len()..],
        1 => [s, "000000000000000"].join("")[..16],
        _ => ["00", s, "0000000000000"].join("")[..16],
    };
    c.to_string()
}

ビルド時に、次のエラーが発生します。

error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
 --> src\main.rs:9:9
  |
9 |     let c = match pad {
  |         ^ `str` does not have a constant size known at compile-time
  |
  = help: the trait `std::marker::Sized` is not implemented for `str`
  = note: all local variables must have a statically known size

ここで何が問題になっていますか?それを修正する最も簡単な方法は何ですか?

12

TL; DRstrを使用せず、&strを使用します。参照は重要です。


問題はこれに簡略化できます:

fn main() {
    let demo = "demo"[..];
}

&strをスライスしようとしています(ただし、String&[T]Vec<T>などについても同様です)。結果。つまり、demoの型はstrになります。修正するには、&を追加します:

let demo = &"demo"[..];

より広い例では、Stringステートメント内に(matchを介して)割り当てられたjoinを作成し、参照を返そうとしているという事実にも遭遇しています。それに。 Stringmatchの最後にドロップされ、すべての参照が無効になるため、これは許可されません。別の言語では、これはメモリの安全性を損なう可能性があります。

潜在的な修正の1つは、作成されたStringを関数の期間保存して、新しい文字列が作成されるまで割り当てが解除されないようにすることです。

fn choose(s: &str, pad: u8) -> String {
    let tmp;

    match pad {
        0 => {
            tmp = ["000000000000000", s].join("");
            &tmp[s.len()..]
        }
        1 => {
            tmp = [s, "000000000000000"].join("");
            &tmp[..16]
        }
        _ => {
            tmp = ["00", s, "0000000000000"].join("");
            &tmp[..16]
        }
    }.to_string()
}

編集上、おそらくこの関数を書くためのより効率的な方法があるでしょう。 フォーマット機構 には、文字列をパディングするためのオプションがあります。新しい文字列を作成せずに、joinから返された文字列を単に切り捨てることもできます。


それが何を意味するのかを簡潔に説明することは困難です。 Rustには、unsizedのタイプがいくつかあります。最も一般的なタイプは、strおよび[T]です。 &strまたは&[T]。これらのタイプは、Box<str>またはArc<[T]>と表示されることもあります。共通点は、常にこれらのタイプがある種のリファレンス。

これらのタイプにはサイズがないため、スタックの変数に格納することはできません。コンパイラは、それらのために予約するスタックスペースの量を知りません。それがエラーメッセージの本質です。

以下も参照してください。

12
Shepmaster