Confusing behavior when dropping a value with `_ = value`

Why does the first variant compile and the second one doesn't?

struct NonSend {
    ptr: *mut ffi::c_void,
}

fn take_closure(closure: impl Fn() -> () + Send + 'static) {
    _ = thread::spawn(closure).join();
}

// Compiles!
let non_send = NonSend {
    ptr: ptr::null_mut(),
};
take_closure(move || {
    _ = non_send;
});

// Doesn't!
let non_send = NonSend {
    ptr: ptr::null_mut(),
};
take_closure(move || {
    std::mem::drop(non_send);
});

If I extend the example to print thread id, it seems like non_send is not actually sent to the other thread at all. Why?

the underscore expression (and wildcard pattern in let binding) does NOT drop the value: it simply discards (or, ignores) it, like nothing happened. particularly, it does NOT move the value like mem::drop() does.

so the first example, the variable non_send is NOT captured in the closure, while the second one is.

here's an example showing _ does NOT move a value:

struct NonCopy {}

fn compiles() {
    let value = NonCopy {};
    let _ = value; //<-- `value` NOT moved here
    let moved = value;
}

fn error() {
    let value = NonCopy {};
    let _value = value; //<-- value MOVED here
    let moved = value; //<-- error: use of moved value
}

here's another example that might be supprising to new rustaceans:

fn main() {
    unsafe {
        let _: i32 = *std::ptr::null(); //<-??? dereferencing a null pointer
    }
}

you can run it on the playground, nothing will happen (well, except for a lint warning by the compiler), no panic, no crash, no segfault, no nothing! and miri will NOT report UB either.

3 Likes

_x means "unused variable x", but _ means "pretend it doesn't exist".

It doesn't just discard the value, it goes way further and makes the value completely irrelevant like it wasn't even there.

This makes more sense in match where _ avoids matching fields instead of destroying them.

3 Likes

Reusing a recent post:

1 Like

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.