Confusing behaviour of 'let _ = '

From my experience, it is typically assumed by rust programmers that 'let _ = ' simply drops the value. This is sometimes true as well, because if the value on the right hand side is a temporary value, it will indeed be dropped at the line.

But I think a big source of confusion comes when you try to drop something like a file handle or a mutex guard with 'let _ = '. One reason is that there is no actual error that would happen, it would just "work". So it doesn't follow the programmers expectation of dropping the value, while also not giving any good warning or error message as to what is happening.

I think there is no actual usecase for a 'let _ = ' that doesn't drop. If you want to ignore a temporary value, then it already drops. If you want to drop a value, well, it currently does not. I propose that there should be a special case for 'let _ = ' that simply drops the value, since that is how people seem to think it behaves already. I also think that it is a very clean syntax for dropping a value.

#![warn(rust_2018_idioms, clippy::pedantic, clippy::all)]

fn main() {
    let my_string = String::from("Hello, world!");
    let _ = my_string;
    println!("{:?}", my_string);

This code above does not generate a single warning even from a pedantic clippy.

1 Like

Relevant answer on a previous - somewhat related - thread.

In particular the last paragraph:

1 Like

I disagree. The clean (and clear) syntax for dropping a value is drop(my_string). It even says “drop”.


Oh my, drop is in prelude. I had no idea that was the case! Since there seems to have already been a discussion on this I'm not going to try and raise it again, but I'm just wondering, where is the clippy lint to warn against noop let _ = ? Is that planned? Would be very helpful to have in my opinion.


How would clippy distinguish between right hand sides that would and wouldn't trigger the lint?

Clippy has access to type information. It can literally just check if the the is a place and if it has any drop glue.

1 Like

I can't imagine the lint would be hard to implement. If it finds a let _ = expr;, just check if the expr is #[must_use], and if it's not, then emit a warning that the let _ is a noop


Yes I think this is possible. Basically just an inverse must_use lint. I thought you wanted something more complicated.