What happens when assigning to the underscore pattern?

What happens when assigning to the underscore pattern?

17

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?

Share
Improve this question

1

  • 1

    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

    yesterday

1 Answer
1

Reset to default

Highest score (default)

Trending (recent votes count more)

Date modified (newest first)

Date created (oldest first)

27

_ 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` .

Share
Improve this answer

Your Answer

Draft saved
Draft discarded

Post as a guest

Required, but never shown


By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged

or ask your own question.

Leave a Reply

Your email address will not be published. Required fields are marked *