了解铁锈寿命

问题描述 投票:0回答:1

尽管我觉得我清楚地了解了锈的寿命,但我发现我的知识存在差距。 总结一下,为什么此代码无效

struct Token<'a> {
    slice: &'a str,
}

struct WrappedToken<'a>(&'a Token<'a>);

trait ToWrappedToken<'a> {
    fn to(&'a self) -> WrappedToken<'a>;
}

impl<'a> ToWrappedToken<'a> for Token<'a> {
    fn to(&'a self) -> WrappedToken<'a> {
        WrappedToken(self)
    }
}

fn to_wrap<'a>(token: Token<'a>) -> Box<dyn ToWrappedToken<'a> + 'a> {
    Box::new(token)
}

fn main() {
    let token = Token {
        slice: "It's working well.",
    };
    let r = to_wrap(token);
    r.to();
}

错误:

error[E0597]: `*r` does not live long enough
  --> src/main.rs:26:5
   |
25 |     let r = to_wrap(token);
   |         - binding `r` declared here
26 |     r.to();
   |     ^ borrowed value does not live long enough
27 | }
   | -
   | |
   | `*r` dropped here while still borrowed
   | borrow might be used here, when `r` is dropped and runs the destructor for type `Box<dyn ToWrappedToken<'_>>`

For more information about this error, try `rustc --explain E0597`.

但事实并非如此。据我所知,该代码应该是有效的。如果它无效,那么为什么此代码有效。我刚刚用参考替换了

Box
。仅此而已。

struct Token<'a> {
    slice: &'a str,
}

struct WrappedToken<'a>(&'a Token<'a>);

trait ToWrappedToken<'a> {
    fn to(&'a self) -> WrappedToken<'a>;
}

impl<'a> ToWrappedToken<'a> for Token<'a> {
    fn to(&'a self) -> WrappedToken<'a> {
        WrappedToken(self)
    }
}

fn to_wrap<'a>(token: &'a Token<'a>) -> &'a dyn ToWrappedToken<'a> {
    token
}

fn main() {
    let token = Token {
        slice: "It's working well.",
    };

    let r = to_wrap(&token);

    r.to();
}

两者都应该在这里有效。

rust scope lifetime reference-lifetimes
1个回答
0
投票

我认为问题出在

&'a Token<'a>
里面的
WrappedToken
。这种构造几乎总是一个错误:当您创建这样的值时,基本上您永远借用了该值,因为引用必须与类型一样长。

正如@vallentin上面的评论,在你的代码中你有一个

Token<'static>
,所以当你调用
to()
时,你借用它并尝试将其转换为
&'static Token<'static>
,但你的变量是本地的
main
,并且它无法检查一下。

如果你这样写,一切正常:

struct WrappedToken<'a, 's>(&'s Token<'a>);

trait ToWrappedToken<'a> {
    fn to<'s>(&'s self) -> WrappedToken<'a, 's>;
}

impl<'a> ToWrappedToken<'a> for Token<'a> {
    fn to<'s>(&'s self) -> WrappedToken<'a, 's> {
        WrappedToken(self)
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.