特征方法中的 Rust 生命周期不匹配

2024-03-27

我正在阅读 Rust 书,并尝试实现逻辑以允许文本仅添加到博客中Post如果它在Draft状态,可以发现here https://doc.rust-lang.org/stable/book/ch17-03-oo-design-patterns.html(建议的练习之一)。

这个想法是使用结构和特征来实现 Rust 中的状态模式。我只是想将字符串切片传递给默认实现add_text如果不在其中,则返回一个空字符串切片Draft状态。然后我将覆盖默认实现Draft状态并返回为中的文本传入的字符串切片Draft state.

pub struct Post {
    state: Option<Box<dyn State>>,
    content: String,
}

impl Post {
    pub fn new() -> Post {
        Post {
            state: Some(Box::new(Draft {})),
            content: String::new(),
        }
    }

    pub fn add_text(&mut self, text: &str) {
        let text = self.state.as_ref().unwrap().add_text(text);
        // self.state.as_ref().unwrap().add_content(text)
        self.content.push_str(text);
    }

    //snip

trait State {
    fn request_review(self: Box<Self>) -> Box<dyn State>;
    fn approve(self: Box<Self>) -> Box<dyn State>;
    fn content<'a>(&self, post: &'a Post) -> &'a str {
        ""
    }
    fn reject(self: Box<Self>) -> Box<dyn State>;
    fn add_text(&self, text: &str) -> &str {
        ""
    }
}

struct Draft {}

impl State for Draft {
    fn request_review(self: Box<Self>) -> Box<dyn State> {
        Box::new(PendingReview {})
    }
    fn approve(self: Box<Self>) -> Box<dyn State> {
        self // don't want to approve a draft before review!
    }
    fn reject(self: Box<Self>) -> Box<dyn State> {
        self // reject doesn't do anything on a draft!
    }
    fn add_text(&self, text: &str) -> &str {
        text
    }
}

我在上面的最后一个方法中遇到了终身不匹配add_text inside impl State for Draft。消息内容如下:

lifetime mismatch

...but data from `text` is returned hererustc(E0623)
lib.rs(67, 30): this parameter and the return type are declared with different lifetimes...
lib.rs(67, 39):
lib.rs(68, 9): ...but data from `text` is returned here

我是 Rust 新手,在这种情况下无法获得正确的生命周期注释。我尝试了显式的生命周期注释,但没有帮助。另外,我知道因为参考文献之一是&self所有生命周期参数应具有相同的生命周期&self自动(我认为?)。

有人可以启发我编译这段代码吗?它对于将来使用这本书的人也可能有用。


你被绊倒了生命周期省略规则 https://doc.rust-lang.org/nomicon/lifetime-elision.html:

输入位置中的每个被省略的生命周期都成为一个独特的生命周期参数。

如果恰好存在一个输入生命周期位置(是否已省略),则该生命周期将分配给所有已省略的输出生命周期。

如果有多个输入生命周期位置,但其中之一是&self or &mut self, 的寿命self被分配给所有省略的输出生命周期。

否则,忽略输出寿命是错误的。

在你的代码中fn add_text(&self, text: &str) -> &str,返回的&str从中获取被忽略的生命周期&self,但它实际上是第二个参数。不匹配就好像:

fn add_text<'a, 'b>(&'a self, text: &'b str) -> &'a str {
    text
}

诀窍是在这里明确生命周期:

trait State {
    fn add_text<'a>(&'a self, text: &'a str) -> &'a str;
}

impl State for Draft {
    fn add_text<'a>(&'a self, text: &'a str) -> &'a str {
        text
    }
}

如果你想要一个稍微更通用的版本:

trait State {
    fn add_text<'a, 'b: 'a>(&'a self, text: &'b str) -> &'a str;
}

impl State for Draft {
    fn add_text<'a, 'b: 'a>(&'a self, text: &'b str) -> &'a str {
        text
    }
}

这里说只要text比寿命长&self一切都很好。您可以决定是否值得花费额外的通用生命周期。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

特征方法中的 Rust 生命周期不匹配 的相关文章

随机推荐