Telling Rust that it's okay to move a value

As you can see in the following code, stdout is moved in drop(stdout), so Rust complains that I can't do that because stdout will be used again here: write!(stdout, "Command executed successfully!\r\n").unwrap();

use std::io::Write;
use std::marker::Send;
    
struct CmdRunner {}

impl CmdRunner {
    pub fn run<W: Write + Send>(&mut self, mut stdout: W) {
        std::thread::scope(|s| {
            // This is listening to Ctrl + C in the actual code

            s.spawn(|| {
                write!(stdout, "Ctrl + C was pressed").unwrap();
                drop(stdout); // Exit raw mode
                std::process::exit(0)
            });
        });

        write!(stdout, "Command executed successfully!\r\n").unwrap();
    }
}

fn handle_cmd_input<T: Write>(stdout: &mut T) {
    write!(stdout, "Input handled!\r\n").unwrap();
}

fn handle_cmd_run<T: Write + Send>(mut stdout: T) {
    handle_cmd_input(&mut stdout);

    let mut cmd_runner = CmdRunner {};

    cmd_runner.run(stdout);
}

fn main() {
    let stdout = Vec::new();

    handle_cmd_run(stdout);
}

But it won't be used again because the process will exit. Can I tell that to Rust and remove the move error?

Or maybe that's not possible and my only option is to use Mutex?

The complier should probably also complain without the drop, because the other thing this code does is mutably access, for the write operation, the stdout variable from two places. And arguing about exit exiting the program won't help with that shared mutable access, as far as I can tell - unless I misunderstood what you're saying about your code, there is nothing preventing the ctrl+c handling to fire while the other write is currently running, so using a Mutex and waiting for concurrent write! to complete first is pretty much unavoidable anyways, as far as I can tell.

The Option is not too much trouble then. I mean, probably you could technically avoid it because of the exit exiting, if you used API like replace_with - Rust, but maybe using an Option feels more straightforward anyways. (And avoids one extra dependency.)

Thanks for the advice, Sakamoto.

Strange, Rust doesn't complain if I comment out drop(stdout): Rust Playground

It's Sakamoto-san :smirk_cat:

Oh, nevermind, I missed the scope! Does this mirror the original code, in that the ctrl+c handling is also confined to a thread::scope before the final write? In this case, you don't actually need the Mutex though, just an Option is enough; you could maybe even avoid that Option with replace_with::replace_with_or_abort.

1 Like

Thanks a lot! I'll try that out.

Update: It worked in the original code! I can't believe the solution was a simple Option. Things were getting a little complicated with Mutex.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.