Search code examples
rustreference

My Rust code has "cannot return value referencing temporary value" error. Why and where?


Note: I'm still new to Rust

I created a function to get the file name of the current exe (not the full path).

fn exe_name() -> Result<Option<&'static OsStr>, Box<dyn Error>> {
    Ok(env::current_exe()?.file_name())
}

But the code won't compile:

$ cargo clippy
...
error[E0515]: cannot return value referencing temporary value
 --> src/libs.rs:8:5
  |
8 |     Ok(env::current_exe()?.file_name())
  |     ^^^-------------------^^^^^^^^^^^^^
  |     |  |
  |     |  temporary value created here
  |     returns a value referencing data owned by the current function

For more information about this error, try `rustc --explain E0515`.
...

I've checked rustc --explain E0515 and search on internet (and StackOverflow too), so basically I can't return a reference to a local var, because it'll get destroyed when the function ends. Still, I dont' know where are actually the problematic part of my code. Can you explain about it?

Oh, I have tried this code that still didn't work:

Ok(env::current_exe()?.to_owned().file_name())
Ok(env::current_exe()?.clone().file_name())

Solution

  • The error is because current_exe returns PathBuf, witch is an owned value.

    When file_name is called on PathBuf, it is refrencing a piece of the path stored in PathBuf. So when the function returned, the reference is no longer refrencing data owned by anything.

    It is equivilent to

    fn example() -> &str {
        let s = String::new("hello");
        &s
    }
    
    

    You have noticed that the return value of your function needs some sort of lifetime witch you have set to `static, meaning the entire length of the program, witch is not correct.

    So is that lifetime returned from file_name actually referring to? In this case, the lifetime is one that is returned by the exe_name function, so it can not be returned.

    To get your function working, you need to make the result of file_name an owned value, not current_exe.

    fn exe_name() -> Result<Option<OsString>, Box<dyn Error>> {
        Ok(env::current_exe()?.file_name().map(|name| name.to_owned()))
    }