How to return the ownership of a std::process::Command variable

Hello, rustacians!

I am new to Rust. I have a question about functions and returning ownership.

I would like to return ownership of a std::process::Command variable but I am not able to do it. Rust compiler complains

fn templar_cmd_with_conf(conf: &str) -> Command {
   let tmp_dir = TempDir::new().expect("temp_dir failed");
   let tmp_dir = tmp_dir.path().to_str().unwrap();
   let conf_file: PathBuf = [tmp_dir, ".templar.toml" ].iter().collect();
   std::fs::write(conf_file, conf).unwrap();
   return Command::cargo_bin("templar").unwrap().arg("--home").arg(tmp_dir);
}

The compilation error I get is:

   Compiling templar v0.1.0 (C:\Users\Kostas\dev\workspace\templar)
   error[E0308]: mismatched types
   --> tests\templar.rs:302:12
   |
  296 | fn templar_cmd_with_conf(conf: &str) -> Command {
  |                                         ------- expected `std::process::Command` because of 
  return type
  ...
  302 |     return Command::cargo_bin("templar").unwrap().arg("--home").arg(tmp_dir);
  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
  expected struct `std::process::Command`, found `&mut std::process::Command`
  error: aborting due to previous error

  For more information about this error, try `rustc --explain E0308`.

Clearly the arg function returns a mutable reference (https://doc.rust-lang.org/std/process/struct.Command.html#method.arg).

Do you know how I convert the mutable reference to an owned variable?

Thank you in advance,

Kostas

To this particular question, using mem::replace to put something in its stead lets you "snap" ownership of the value:

mem::replace(your_mut_ref, somme_dummy_value)

See, for instance, mem::take()'s implementation:


Now, regarding your issue at hand, you do not need to resort to these swapping shenanigans.

Indeed, you create the Command and are thus able to own it; it's just that you let it be an ephemeral variable and by so doing you are relinquishing ownership of it.

So the solution is simple: don't do it, don't let the created command be an unnamed / unbound / anonymous / temporary / ephemeral variable:

Command::cargo_bin("templar").unwrap().arg("--home")...
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this is an owned Command,
                              but it is not bound to a variable name

and instead, bind it to a variable name:

fn templar_cmd_with_conf (conf: &'_ str)
  -> Command
{
    let tmp_dir = TempDir::new().expect("temp_dir failed");
    let tmp_dir = tmp_dir.path().to_str().unwrap();
    let conf_file: PathBuf = [tmp_dir, ".templar.toml" ].iter().collect();
    ::std::fs::write(conf_file, conf).unwrap();

    let mut cmd: Command = Command::cargo_bin("templar").unwrap();
    cmd.arg("--home").arg(tmp_dir) /* of type &mut Command */;
    /* return */ cmd
}
3 Likes

Make sense, simple! Thanks Yandros :slight_smile:

1 Like