Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can you manipulate Rust env::args and avoid "temporary value dropped while borrowed"?

Tags:

rust

I have no idea how to follow the compiler suggestion: consider using a let binding to create a longer lived value.

Playground

#![allow(unused)]
fn main() {
let a_dir=std::env::args().nth(2);
    
    let  dir:&str=match a_dir{
      Some (ref a)=> &format!("./{}/**/*.liquid",a) as &str,
      None=>{"./**/*.liquid"},
    };
}
error[E0716]: temporary value dropped while borrowed
 --> src/main.rs:6:23
  |
5 |     let  dir:&str=match a_dir{
  |          --- borrow later stored here
6 |       Some (ref a)=> &format!("./{}/**/*.liquid",a) as &str,
  |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^       - temporary value is freed at the end of this statement
  |                       |
  |                       creates a temporary which is freed while still in use
  |
  = note: consider using a `let` binding to create a longer lived value
like image 206
skatori Avatar asked Oct 15 '25 18:10

skatori


1 Answers

#![allow(unused)]
fn main() {
    let a_dir = std::env::args().nth(2);

    let dir: &str = match a_dir {
        Some(ref a) => &format!("./{}/**/*.liquid", a) as &str,
        None => "./**/*.liquid",
    };
}

In your code, inside the Some case of match, you are creating an owned String. Which is dropped at the end of you match block.

format!("./{}/**/*.liquid", a);

This produces a String and you return a reference to it.

But at the end of the match block, the String produced by format!() has actually dropped so you are trying to return a dangling reference because of which compiler rejects your code.


"consider using a let binding to create a longer lived value"

In simple terms, compiler is suggesting you to create the String before and store it somewhere so it doesn't get dropped and you are able to return a valid reference.

Going by the compiler's suggestion:

#![allow(unused)]
fn main() {
    let a_dir = std::env::args().nth(2);

    let string;
    let dir: &str = match a_dir {
        Some(ref a) => {
            string = format!("./{}/**/*.liquid", a);
            &string
        },
        None => "./**/*.liquid",
    };
}

This will create a variable named string that will live long enough and you store the String being generated from format!() in the string. Then you return the reference to the string.

Although a better way would be to use a String instead here:

#![allow(unused)]
fn main() {
    let a_dir = std::env::args().nth(2);
    
    let dir = a_dir
        .as_ref()
        .map(|val| format!("./{}/**/*.liquid", val))
        .unwrap_or_else(|| "./**/*.liquid".to_string());
}

If you ever want &str you can simply do dir.as_str().

like image 162
Mihir Luthra Avatar answered Oct 18 '25 16:10

Mihir Luthra



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!