[英]What does “`str` does not have a constant size known at compile-time” mean, and what's the simplest way to fix it?
我正在嘗試操作從函數參數派生的字符串,然后返回該操作的結果:
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
這里出了什么問題,解決它的最簡單方法是什么?
TL;DR不要使用str
,使用&str
。 參考很重要。
問題可以簡化為:
fn main() {
let demo = "demo"[..];
}
您正在嘗試對&str
進行切片(但對於String
、 &[T]
、 Vec<T>
等也會發生同樣的情況),但沒有引用結果。 這意味着demo
的類型將是str
。 要修復它,請添加&
:
let demo = &"demo"[..];
在您更廣泛的示例中,您還遇到了這樣一個事實,即您正在match
語句(通過join
)中創建分配的String
,然后嘗試返回對它的引用。 這是不允許的,因為String
將在match
結束時被刪除,從而使任何引用無效。 在另一種語言中,這可能會導致內存不安全。
一種可能的解決方法是在函數執行期間存儲創建的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]>
。 共同點是它們總是在某種引用后面使用。
因為這些類型沒有大小,它們不能存儲在堆棧上的變量中——編譯器不知道要為它們保留多少堆棧空間! 這就是錯誤信息的本質。
也可以看看:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.