Why does the variable not live long enough?

lifetime, object-lifetime, rust

Solution

This isn't a bug. The "problem" here is `as_slice`'s definition. It takes a reference to its arguments, and returns a `&str` with the same lifetime as the reference, it can't introspect into the internal lifetimes of whatever type it is being called on. That is, `path_str.as_slice()` returns a `&str` that lasts for as long as `path_str`, not as long as the data `path_str` points at (the original `Path`).

In other words, there's two lifetimes here. I'll use a hypothetical block-lifetime annotation syntax on the example from @Arjan's filed bug (this answer is based of my response there).

fn test<'a>(s: &'a String) -> &'a str {
    'b: {
        let slice: &'a str = s.as_slice();
        slice.as_slice()
    }
}

For the second `as_slice` call we have `self: &'b &'a str`, and thus it returns `&'b str`, which is too short: `'b` is just local to `test`.

As you discovered, the fix now is just removing the extraneous `as_slice` call. However, with dynamically sized types (DST), we will be able to write `impl StrSlice for str`, and then `slice.as_slice()` will be returning a `&'a str`, since there won't be an extra layer of references (that is, `self: &'a str`).

Problem

Consider this function that should return the file extension of a given `Path`. ``` pub fn get_extension<'a>(path: &'a Path) -> Option<&'a str> { let path_str = path.as_str().unwrap(); let ext_pos = regex!(".[a-z0-9]+$").find(path_str); match ext_pos { Some((start, _)) => { return Some(path_str.as_slice().slice_from(start)) }, None => return None } } ``` The error message is as follows: ``` `path_str` does not live long enough ``` The error message is pretty clear and it's a shame I can't work it out on my own. I understand it in theory but there are still a couple of blurred things for me. I understand that the compiler wants to tell me that `path_str` does not live long enough to be valid as the return value with is marked with lifetime `'a`. But this is where it stops for me: I understand that the reference to `path` (the input parameter) should life exactly as long as the reference to the `str` that is wrapped in the `Option` (the output parameter) since we return `Some(path_str.as_slice().slice_from(start))` I assume that in practice that means that `path_str` needs to live as long as `path`. What I don't understand is why exactly does `path_str` not live long enough and how could I fix this? What makes it die to soon? UPDATE As pointed out in the comments and also on IRC removing the superflous `as_slice()` makes the code compile. Does anyone know why that is? It was also pointed out that there exists a method to get the extension directly. But yep, I'm actually more interested in learning the story behind the problem though.

Original source