0

I'm writing an application that needs to lookup the path of a binary using which. I already found out how to run a command, but I can't store the output.stdout to a variable that I can use.

use std::process::Command;
use std::str;

fn main() {
    let interpreter: &str = "php72";
    let binary: &str = "composer";
    let mut _binary_path: &str = "";

    if interpreter != "" {
        let output = Command::new("which")
            .arg(binary)
            .output()
            .expect("Execution of 'which' failed.");
        _binary_path = str::from_utf8(&output.stdout).unwrap();
    }
}

playground

This results in the following error:

error[E0597]: `output.stdout` does not live long enough
  --> src/main.rs:14:40
   |
14 |         _binary_path = str::from_utf8(&output.stdout).unwrap();
   |                                        ^^^^^^^^^^^^^ borrowed value does not live long enough
15 |     }
   |     - `output.stdout` dropped here while still borrowed
16 | }
   | - borrowed value needs to live until here

Borrowing and referencing is still a bit confusing to me, even though I've read the docs. I understand that the lifetime of output is limited, since it lives in an if statement. I don't understand why it won't let me copy the value to the scope of the main() function.

What's going on? What's the best way to read the stdout?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Timon de Groot
  • 7,255
  • 4
  • 23
  • 38
  • 1
    `output`'s lifetime is within your `if interpreter != "" {` branch - a simple solution is to use the owned `String` type, it'll also probably help the ergonomics of your code. The `String` can be passed as `&str` further down the line by: `&String` - see: https://play.rust-lang.org/?gist=f452d442e10c3a36c5c345aabd6d152f&version=stable&mode=debug&edition=2015 – Martin Gallagher Sep 22 '18 at 14:54

1 Answers1

2

binary_path is a &'static str because it is initialized to a string literal. The result of calling str::from_utf8 is a &str with a shorter lifetime than that. You cannot make the value live longer. This is a huge reason that Rust exists.

The simplest thing you can do is switch to a String:

let mut binary_path = String::new();

if interpreter.is_empty() {
    // ...
    binary_path = String::from_utf8(output.stdout).unwrap();
}

You could also use a Cow if you benchmarked that always allocating the binary_path is poor for performance.

See also:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366