Where did the 'static lifetime come from

前端 未结 1 645
旧时难觅i
旧时难觅i 2021-01-15 19:02

I\'ve got the following code (doesn\'t make much sense, just a minimised test case):

extern crate rustc_serialize;

use rustc_serialize::json::Json;
use std:         


        
1条回答
  •  时光说笑
    2021-01-15 19:42

    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) -> Result<(), Box> {
        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![]);
    }
    

    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.

    So what is going on there?

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

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

    Here we see another key point: the type Box 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".

    And now we look at our function signature and see Result<(), Box>: 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 the lifetime bound 'static is added. Thus the return type explicitly written out is Result<(), Box>.

    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) -> Result<(), Box> {
        ...
    }
    

    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.

    0 讨论(0)
提交回复
热议问题