4

I have a function which receive some parameter, but when I try to use the parameter, it throw an error.

// the function

pub fn solc_compile(compiler: &str, file: &str, out: &str, config: templates::Config) {
    let mut args = vec![
        "--bin",
        "--abi",
        "--include-path",
        "./libs",
        "--include-path",
        "./node_modules",
        "--output-dir",
        out,
    ];

    if config.compiler.optimize {
        let runs: &str = config.compiler.runs.to_string().as_str();
        args.push("--optimize");
        args.push("--optimize-runs");
        args.push(runs);
    }
}

// config type using on the function parameter (config templates::Config).

templates.rs

// config templates.
#[derive(Deserialize, Serialize)]
pub struct Config {
    pub info: ConfigInfo,
    pub compiler: ConfigCompiler,
}

// config.info templates.
#[derive(Deserialize, Serialize)]
pub struct ConfigInfo {
    pub name: String,
    pub license: String,
}

// config.compiler templates.
#[derive(Deserialize, Serialize)]
pub struct ConfigCompiler {
    pub solc: String,
    pub optimize: bool,
    pub runs: i64,
}

And this is the error I've got when run cargo build.

error[E0716]: temporary value dropped while borrowed
  --> src/solc.rs:58:26
   |
58 |         let runs: &str = config.compiler.runs.to_string().as_str();
   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^         - temporary value is freed at the end of this statement
   |                          |
   |                          creates a temporary which is freed while still in use
...
61 |         args.push(runs);
   |                   ---- borrow later used here
   |
   = note: consider using a `let` binding to create a longer lived value
Caesar
  • 6,733
  • 4
  • 38
  • 44
ade ramdani
  • 333
  • 1
  • 3
  • 12
  • 1
    Does this answer your question? [Why does the compiler tell me to consider using a \`let\` binding" when I already am?](https://stackoverflow.com/questions/28893183/why-does-the-compiler-tell-me-to-consider-using-a-let-binding-when-i-already) – E_net4 Jan 25 '22 at 11:14
  • The value obtained from `config.compiler.runs.to_string()` is not assigned to a variable, so it is dropped prematurely. See also: https://stackoverflow.com/questions/28469667/borrowed-value-does-not-live-long-enough-when-using-the-builder-pattern https://stackoverflow.com/questions/37264396/borrowed-value-does-not-live-long-enough-seems-to-blame-the-wrong-thing https://stackoverflow.com/questions/47662253/why-is-it-legal-to-borrow-a-temporary – E_net4 Jan 25 '22 at 11:16
  • I asked a concise Question for common rust error `error[E0716]` [error E0716: temporary value dropped while borrowed (rust)](https://stackoverflow.com/questions/71626083/error-e0716-temporary-value-dropped-while-borrowed-rust). It links back to this Question. – JamesThomasMoon Mar 26 '22 at 07:25

1 Answers1

6

You create a new String with to_string, but don't give it a variable to live in, so it dies at the next ;. You can solve that by not calling as_ref immediately:

if config.compiler.optimize {
    let runs: String = config.compiler.runs.to_string();
    // ..
    args.push(runs.as_ref());
}

But now you have the next problem: your args vector contains string references, but the string in runs dies at the end of the if block. It must be able to live at least as long as args. You can solve this by splitting declaration and assignment for args:

let runs: String;
if config.compiler.optimize {
    runs = config.compiler.runs.to_string();
    // ...
    args.push(runs.as_str());
}

Another possibility would be to make args a Vec<String>.

Caesar
  • 6,733
  • 4
  • 38
  • 44