Nie mam pojęcia, jak postępować zgodnie z sugestią kompilatora: consider using a let binding to create a longer lived value.

Plac zabaw

#![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
0
skatori 22 listopad 2020, 11:47

1 odpowiedź

Najlepsza odpowiedź
#![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",
    };
}

W swoim kodzie, wewnątrz meczu Some tworzysz własność String. Który jest upuszczony na końcu dopasowania blokady.

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

Wytwarza to String I zwracasz do niego odniesienie.

Ale na końcu bloku meczu, String wytworzona przez format!() faktycznie upuściła, dzięki czemu próbujesz zwrócić zwisające odniesienie, ponieważ kompilator odrzuca kod.


"Rozważ użycie wiązania, aby utworzyć dłuższą wartość"

W prostych warunkach, kompilator sugeruje, abyś stworzyć String przed i przechowywać go gdzieś, więc nie zostanie uproszczony i jesteś w stanie zwrócić prawidłowe odniesienie.

Przejście przez sugestię kompilatora:

#![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",
    };
}

Spowoduje to utworzenie zmiennej o nazwie string, który będzie żył wystarczająco długo i przechowuje String generowany z format!() w string. Następnie zwracasz odniesienie do string.

Chociaż lepszy sposób byłby użycie String zamiast tego:

#![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());
}

Jeśli kiedykolwiek chcesz &str możesz po prostu zrobić dir.as_str().

3
Mihir 22 listopad 2020, 10:18