rust-lang / rust-lang/rust-clippy
Flag let _ = ... as dangerous
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 13.5k
- Forks
- 2.2k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 32
Description
What it does
If you write code like this:
let _ = lock.lock();
The guard will drop and you will not hold the lock. This catches a lot of people by surprise and has potentially disastrous consequences. (See prior discussion of this here https://github.com/rust-lang/rust/issues/10488)
If instead you write
let _guard = lock.lock();
You will hold the lock until _guard is dropped out of scope. This is almost always what people want for something RAII-like such as a lock (or file handle, DB transaction, etc.)
If the let _ = lock.guard() construction was considered hazardous, we could instead use the following alternatives to be explicit about what we want:
- Either explicitly drop:
drop(lock.lock());(which in this case makes the mistake obvious) - Or name the variable:
let _guard = lock.lock();
Because let _ = ... is subtly hazardous, and there are more explicit constructions to do the same thing, I would personally like to ban this pattern in my own code.
NOTE: As a more practical example in real code, I made a fix in some code a while back https://github.com/amethyst/distill/commit/e7e1d254816096dad220cb4571b0cdd6bf245eb9 and originally tried to write it as let _ = self.0.runtime.enter(); which was no different from before. There are also other examples of people hitting this in https://github.com/rust-lang/rust/issues/10488
Lint Name
let_underscore_can_be_hazardous
Category
correctness
Advantage
Potentially catches serious resource management problems
Drawbacks
Lots of people probably like the let _ = X construction for things like receiving a result as a return value and explicitly deciding to not check it. This is by many considered the idiomatic way to ignore a return value.
It would be nice if there was a way to apply this lint only when the returned object is an RAII-style object. (Similar to how unused Results are flagged.) But I'm not sure how practical that would be, especially considering containers and opaque trait objects.
Example
let _ = function_call(x);
Depending on intent, could be written as:
drop(function_call(x)); or let _unused = function_call(x);
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the proposed let _ = ... examples and the prior discussion in rust-lang/rust#10488; the issue names no files, tests, or entry points. Define the lint’s intended scope and handling of RAII-style values versus intentionally ignored results, then verify that the behavior and rationale are documented and tested.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100