“`str` 在编译时没有已知的常量大小"是什么意思,最简单的修复方法是什么? [英] What does “`str` does not have a constant size known at compile-time” mean, and what's the simplest way to fix it?

查看:21
本文介绍了“`str` 在编译时没有已知的常量大小"是什么意思,最简单的修复方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试操作从函数参数派生的字符串,然后返回操作的结果:

I'm trying to manipulate a string derived from a function parameter and then return the result of that manipulation:

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()
}

在构建时,我收到此错误:

On building, I get this error:

error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
 --> srcmain.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

这里出了什么问题,最简单的修复方法是什么?

What's wrong here, and what's the simplest way to fix it?

推荐答案

TL;DR 不要使用str,使用&str.参考很重要.

TL;DR Don't use str, use &str. The reference is important.

问题可以简化为:

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

您正在尝试对 &str 进行切片(但对于 String&[T]Vec 等),但没有引用结果.这意味着 demo 的类型将是 str.要修复它,请添加 &:

You are attempting to slice a &str (but the same would happen for a String, &[T], Vec<T>, etc.), but have not taken a reference to the result. This means that the type of demo would be str. To fix it, add an &:

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

在更广泛的示例中,您还遇到了在 match 语句内创建分配的 String 的事实(通过 join) 然后尝试返回对它的引用.这是不允许的,因为 String 将在 match 的末尾被删除,从而使任何引用无效.在另一种语言中,这可能会导致内存不安全.

In your broader example, you are also running into the fact that you are creating an allocated String inside of the match statement (via join) and then attempting to return a reference to it. This is disallowed because the String will be dropped at the end of the match, invalidating any references. In another language, this could lead to memory unsafety.

一个潜在的解决方法是在函数的持续时间内存储创建的String,防止在创建新字符串之前释放它:

One potential fix is to store the created String for the duration of the function, preventing its deallocation until after the new string is created:

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 返回的字符串,而无需创建新字符串.

Editorially, there's probably more efficient ways of writing this function. The formatting machinery has options for padding strings. You might even be able to just truncate the string returned from join without creating a new one.

这意味着什么更难以简洁地解释.Rust 有许多未调整大小的类型.最流行的是str[T].将这些类型与您通常看到的使用方式进行对比:&str&[T].您甚至可能将它们视为 BoxArc<[T]>.共同点是它们总是在某种类型的引用后面使用.

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.

另见:

这篇关于“`str` 在编译时没有已知的常量大小"是什么意思,最简单的修复方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆