且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

“静态生命周期"从何而来

更新时间:2023-01-25 17:51:39

这里有很多事情要做.为了解释它,让我们看一下您的问题的这个更简化的版本.为了避免隐藏东西,我还用它的 explicit 替换了 try!()形式.

It's quite a bit going on here. In order to explain it, let's look at this even more simplified version of your problem. To avoid hiding things, I also replaced the try!() with its explicit form.

enum SomeError<'a> {
    Something(&'a str),
    Other,
}

// ... impls Debug, Display, Error for SomeError ...

fn do_stuff(doc: &u32) -> Result<(), SomeError> { Ok(()) }

fn get_things(doc: &Vec<u32>) -> Result<(), Box<Error>> {
    match do_stuff(&v[0]) {   // `try!` expands into this match 
        Ok(v) => Ok(v),
        Err(e) => Err(e.into()),
    }  //             ^^^^^^^^--- #1

}

fn main() {
    let _ = get_things(&vec![]);
}

这是第一件可能令人困惑的事情:try! 调用 std::convert::From::from(e)(或等效的,但更短:e.into()).这意味着有趣的地方只是标有 #1 的部分.

This is the first thing that might be confusing: try! calls std::convert::From::from(e) (or equivalent, but shorter: e.into()). This means that the interesting spot is only the part marked with #1.

那么那里发生了什么?

调用 into() 意味着 Rust 编译器必须为 SomeError 搜索 Into> 的某些实现.通过神奇的 impl;进入<U>对于 T where U: From<T> 间接,编译器会找到一些可能可行的实现,特别是这个:

Calling into() means that the Rust compiler has to search for some implementation of Into<Box<Error>> for SomeError. Through the magic impl<T, U> Into<U> for T where U: From<T> indirection, the compiler finds a few implementations that might work out, notably this one:

impl<'a, E: Error + 'a> From<E> for Box<Error + 'a>

在这里我们看到另一个关键点:类型 Box 有一个生命周期界限.简单的英语类型会读成这样:一个实现特征 Error 并且至少在生命周期 'a 内存活的装箱类型".

Here we see another key point: the type Box<Error + 'a> has a lifetime bound in it. The type in plain English would read something like: "a boxed type that implements the trait Error and is alive at least for the lifetime 'a".

现在我们查看我们的函数签名并看到 Result>:它没有生命周期的限制!嗯……我们没有明确地写出一个,但编译器还是添加了一个,因为这是处理这种盒装特征的唯一方法.这个 RFC 是关于编译器的默认生命周期界限自动添加.并且对于 Box 生命周期绑定 'static 被添加.因此明确写出的返回类型是Result>.

And now we look at our function signature and see Result<(), Box<Error>>: it doesn't have a lifetime bound in it! Well... we didn't explicitly write one out, but the compiler adds one anyway, because it's the only way to work with such boxed traits. This RFC is about default lifetime bounds that the compilers adds automagically. And for Box<Trait> the lifetime bound 'static is added. Thus the return type explicitly written out is Result<(), Box<Error + 'static>>.

要使您的代码编译,请向输入参数添加显式生存期到输出类型,如下所示:

To make your code compile, add an explicit lifetime to the input parameter and to the output type, like so:

fn get_things<'a>(doc: &'a Vec<u32>) -> Result<(), Box<Error + 'a>> {
    ...
}

这样你就可以避免默认添加的 'static 生命周期限制,并告诉编译器你的盒子里的东西只需要和你的输入参数一样长.

That way you can avoid the 'static lifetime bound added by default and tell the compiler that the thing in your box only has to life as long as your input parameter.