为什么我不能返回从String生成的& str值?

时间:2015-04-21 19:24:05

标签: rust lifetime

我在尝试理解为什么我无法返回&str生成的String值时遇到了一些麻烦(善良,何时as_str准备就绪? )我做错了什么。我得到了这个想法,因为我所做的一切都没有让这个价值足够长久使用。

我试图为自定义结构实现error::Error

impl error::Error for LexicalError {
    fn description(&self) -> &str {
        let s = format!("{}", self);

        // s doesn't live long enough to do this, I've tried 
        // cloning s and using that, but still the clone doesn't
        // live long enough.
        s.trim()
    }

    fn cause(&self) -> Option<&error::Error> {
        None
    }
}

(对于完整代码段,此处为playpen

我无法弄清楚如何从description返回&amp; str,我想重复使用Display逻辑,除非我完全不知道误解description应该返回的内容(也许是问题的简短描述)。要么,format!(...)返回{{1}}也会遇到同样的问题。这是一个变量,我似乎无法活到足够长的时间对我有用。

1 个答案:

答案 0 :(得分:13)

首先,让我们来看看实际预期的寿命。 description的签名中存在隐含生命周期:

fn description(&self) -> &str
// Can be rewritten as
fn description<'a>(&'a self) -> &'a str

返回的指针必须至少与self一样有效。现在考虑s。它将保存一个String,一个拥有的字符串,它在函数末尾超出范围。返回&s将无效,因为s在函数返回时消失了。 trim返回一个向s借用的字符串切片,但只要s为切片,该切片才会有效。

您需要返回一个比方法调用更长的字符串切片,因此这将排除堆栈中的任何内容。如果您可以自由选择返回类型,解决方案是将字符串移出函数。为此,需要一个拥有的字符串,然后返回类型为String,而不是&str。不幸的是,您无法在此处自由选择返回类型。

要返回一个比方法调用更长的字符串切片,我会看到两个选项:

  1. 使用&'static字符串切片。这肯定比调用更长,但它要求在编译时知道字符串。字符串文字的类型为&'static str。如果描述不包含任何动态数据,则这是一个合适的选项。

  2. 将拥有的字符串存储在LexicalError本身。这可以确保您可以返回指向它的指针,该指针对self的整个生命周期有效。您可以向desc: String添加字段LexicalError,并在构造错误时执行格式设置。然后该方法将实现为

    fn description(&self) -> &str {
        &self.desc
    }
    

    为了重复使用,您可以使Display写相同的字符串。

  3. 根据documentation of ErrorDisplay可用于提供其他详细信息。如果您希望在错误中包含动态数据,那么Display是格式化它的好地方,但您可以省略它description。这将允许使用第一种方法。