Temporary value dropped while borrowed

Hi, this is my first time using the forum.

So my issue is I can't compile my code because I keep getting this error message:

     --> src/main.rs:19:25
       |
    19 |         let path_str = &_path.as_path().display().to_string()[..];
       |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
    ...
    24 |             files.push(&path_str);
       |             ----- borrow later used here
    ...
    30 |     }
       |     - temporary value is freed at the end of this statement
       |
       = note: consider using a `let` binding to create a longer lived value

This is the area of the code the problem is occuring in:

fn get_file_tree(tree_root: &str) {
    let mut files: Vec<&str>;
    //let mut dir: Vec<&str>;

    let paths = fs::read_dir(tree_root).unwrap();

    for path in paths {

        let _path = &path.unwrap().path();
        let path_str = &_path.as_path().display().to_string()[..];

        if _path.is_dir() { // Path is a directory
            let path_str = &path_str[..];
            println!("{}", _path.display());
            files.push(&path_str);
            get_file_tree(&path_str);

        } else { // Path is a file
            println!("{}", _path.display());
        }
    }

I'm brand new to rust, and am currently making my way through the book. I've already done a few google searches and I think I understand that the error is happening as I am trying to add a reference of the temporary "path" variable to a vector outside the for loop's scope? I think I somehow need to copy the variable but I am unsure how?

Anyway thanks in advance for any responses,
Leon

This expression:

_path.as_path().display().to_string()

creates a String. You then use &the_string[..] to borrow that String. Since the String has not been assigned to any variable, it is then destroyed at the end of the line, invalidating the borrow you just took of it.

You probably just want to store the String directly. The same applies a bunch of other places. I assume files is a vector, and you probably just wanted to give the vector ownership of that string. So don't use an ampersand. If you need the string multiple times, then just clone it.

Ok, that makes sense, but when I try to push path_str directly the compiler gives me the message: doesn't have a size known at compile-time.

Now I'm confused because if I use a borrow it will go out of scope too early, but if I push the value directly, the size cannot be known at compile time.

It sounds like the compiler is interpreting one of your values to be str without an ampersand. You should probably post another snippet so I can see where you are at.

Ok yeah:

     fn get_file_tree(tree_root: &str) {
        let mut files: Vec<str>;
        //let mut dir: Vec<&str>;

        let paths = fs::read_dir(tree_root).unwrap();

        for path in paths {

            let _path = &path.unwrap().path();
            let path_str = _path.as_path().display().to_string();

            if _path.is_dir() { // Path is a directory
                let path_str = path_str.clone();
                println!("{}", _path.display());
                files.push(path_str);
            get_file_tree(&path_str);

        } else { // Path is a file
            println!("{}", _path.display());
        }
    }
}

Please fix your code block and include the error message.

I'm guessing your files vector should be changed to have the type Vec<String> instead.

Ok, thanks that works better but now there's one more error:

error[E0381]: borrow of possibly-uninitialized variable: `files`
  --> src/main.rs:24:13
   |
24 |             files.push(path_string);
   |             ^^^^^ use of possibly-uninitialized `files`

error: aborting due to previous error

You need to initialize it.

let mut files: Vec<String> = Vec::new();

Great that works now thanks! (Sorry about the poor formatting of the code blocks :grimacing:)

1 Like

Regarding &str vs String. When you use &str, you're telling the compiler that "Somewhere else in the program, there is a String, and this &str is a reference into that String". Additionally this String somewhere else must live longer than the &str. So if there isn't a String somewhere else, you can't use &str.

1 Like