27

This is a question from Rust quiz 28:

struct Guard;

impl Drop for Guard {
    fn drop(&mut self) {
        print!("1");
    }
}

fn main() {
    let _guard = Guard;
    print!("3");
    let _ = Guard;
    print!("2");
}

Such code prints 3121, in the third line of main, assigning to _ means a immediate drop. However, when transferring the ownership to _ using the following code

struct Guard;

impl Drop for Guard {
    fn drop(&mut self) {
        print!("1");
    }
}

fn main() {
    let _guard = Guard;
    print!("3");
    let _ = _guard;
    print!("2");
}

it prints 321, which means the Guard didn't drop immediately, and _ owns the Guard?

So I'm unsure when assigning a mutex to _ like this let _ = Mutex::lock().unwrap(), will it drop the mutex immediately?

kmdreko
  • 42,554
  • 6
  • 57
  • 106
dpr
  • 319
  • 1
  • 6
  • 2
    Also note that the statement `guard;` moves (and thus drops) `guard`, while `let _ = guard;` does not result in a move. The function `std::mem::drop()` is actually redundant – `drop(x);` and `x;` are completely equivalent. – Sven Marnach May 23 '23 at 06:18

1 Answers1

37

_ means "don't bind this value". When you create a new value on the spot, this means the value is immediately dropped, like you said, since there is no binding to own it.

When you use it with something that's already bound to a variable, the value is not moved, which means the variable retains ownership. So this code works.

let guard = Guard;
let _ = guard;
let _a = guard; // `guard` still has ownership

This also works.

let two = (Guard, Guard);
print!("4");
let (_a, _) = two;
print!("3");
let (_, _b) = two;
print!("2");

This is more useful in match statements, when you want to use the original value after matching, which would normally not work if the inner value was moved.

let res: Result<Guard, Guard> = Ok(Guard);
match res {
    Ok(ok) => drop(ok),
    Err(_) => drop(res), // do something with the whole `Result`
}

If you change the second branch to be Err(_e), you get use of partially moved value: `res` .

drewtato
  • 6,783
  • 1
  • 12
  • 17