3
votes

I'm trying to get the following code working in a build script:

use std::path::PathBuf;
use std::env;
use std::ffi::AsOsStr;

fn main() {
    let mut string = env::var("CARGO_MANIFEST_DIR").unwrap();
    let mut main_dir = PathBuf::new(string);
    main_dir.push("src/dependencies");

    let test_str = main_dir.as_os_str(); // test_str gets the same lifetime as main_dir

    let second_test = test_str.to_str();

    let last_test = second_test.unwrap();
    panic!(&last_test);
}

I get the following errors:

<anon>:10:24: 10:32 error: `main_dir` does not live long enough
<anon>:10         let test_str = main_dir.as_os_str(); // test_str gets the same lifetime as main_dir
                                 ^~~~~~~~
note: reference must be valid for the static lifetime...
<anon>:7:48: 16:6 note: ...but borrowed value is only valid for the block suffix following statement 1 at 7:47
<anon>:7         let mut main_dir = PathBuf::new(string);
<anon>:8         main_dir.push("src/dependencies");
<anon>:9     
<anon>:10         let test_str = main_dir.as_os_str(); // test_str gets the same lifetime as main_dir
<anon>:11     
<anon>:12         let second_test = test_str.to_str();
          ...
<anon>:15:17: 15:26 error: `last_test` does not live long enough
<anon>:15         panic!(&last_test);
                          ^~~~~~~~~
<std macros>:1:1: 12:62 note: in expansion of panic!
<anon>:15:9: 15:28 note: expansion site
note: reference must be valid for the static lifetime...
<anon>:14:45: 16:6 note: ...but borrowed value is only valid for the block suffix following statement 5 at 14:44
<anon>:14         let last_test = second_test.unwrap();
<anon>:15         panic!(&last_test);
<anon>:16     }
error: aborting due to 2 previous errors

I'm literally saving every value in an own variable. So how is this possible to not outlive the statement? I know that there is "into_os_string" as well, but why is my approach not working?

I'm really trying to understand the whole lifetime thing, but it's very difficult. Maybe someone could quickly go through my example and tell me what happens with the lifetimes in each statement and why it's not working? That'd help me a lot

1
Sorry for that, just updated the code to work on playpen ;)Reignbeaux

1 Answers

4
votes

Commenting out lines of code, we can find that it is the panic! line that fails. The first argument of panic! is supposed to be a formatting string, which must have the 'static lifetime, as it's actually compiled.

A small example that replicates this is:

let s = "Foo".to_string();
panic!(&s);

But for some reason, this example has a much better error message, one that points to &s.

For your example, you can just change the panic! line to:

panic!("{}", last_test);