Why does the variable not live long enough?

冷暖自知 提交于 2019-12-19 05:47:29

问题


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.


回答1:


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).



来源:https://stackoverflow.com/questions/24542064/why-does-the-variable-not-live-long-enough

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!