rust-lang / rust-lang/rust-clippy
Another let_and_return false positive
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 13.5k
- Forks
- 2.2k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 32
Description
Summary
There are already a few issues involving let_and_return false positives with E0597, but all of them are closed. I've found another case that still reproduces on Nightly (very similar to the one fixed by https://github.com/rust-lang/rust-clippy/pull/5680).
Lint Name
let_and_return
Reproducer
I tried this code:
struct HasDrop<'i>(core::marker::PhantomData<&'i ()>);
impl<'i> Drop for HasDrop<'i> {
fn drop(&mut self) {}
}
struct DropIterator<'i>(&'i ());
impl<'i> Iterator for DropIterator<'i> {
type Item = HasDrop<'i>;
fn next(&mut self) -> Option<Self::Item> {
None
}
}
fn is_valid() -> bool {
let i = ();
let mut drop_iter = DropIterator(&i);
let x = drop_iter.next().is_none();
x
}
fn main() {
println!("{}", is_valid());
}
The code runs correctly, printing true to the console. However, there is a single clippy lint reported:
warning: returning the result of a `let` binding from a block
--> src/main.rs:20:5
|
19 | let x = drop_iter.next().is_none();
| ----------------------------------- unnecessary `let` binding
20 | x
| ^
|
= note: `#[warn(clippy::let_and_return)]` on by default
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return
help: return the expression directly
|
19 ~
20 ~ drop_iter.next().is_none()
|
After applying the suggestion, the code no longer compiles. The following error is reported:
error[E0597]: `i` does not live long enough
--> src/main.rs:18:38
|
18 | let mut drop_iter = DropIterator(&i);
| ^^ borrowed value does not live long enough
19 | drop_iter.next().is_none()
| ---------------- a temporary with access to the borrow is created here ...
20 | }
| -
| |
| `i` dropped here while still borrowed
| ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Option<HasDrop<'_>>`
|
= note: the temporary is part of an expression at the end of a block;
consider forcing this temporary to be dropped sooner, before the block's local variables are dropped
help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block
|
19 | let x = drop_iter.next().is_none(); x
| +++++++ +++
For more information about this error, try `rustc --explain E0597`.
I expected to see this happen:
The original code should not suggest any clippy lints.
Version
rustc 1.59.0-nightly (db9d361a4 2021-11-28)
binary: rustc
commit-hash: db9d361a4731ca0bb48533fab6297a8fea75696f
commit-date: 2021-11-28
host: x86_64-unknown-linux-gnu
release: 1.59.0-nightly
LLVM version: 13.0.0
Additional Labels
@rustbot label +I-suggestion-causes-error
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 let_and_return lint and reproduce the supplied Rust example on the referenced Nightly version. Investigate why its suggestion changes the borrow-checking result, then add coverage showing that this case receives no lint and verify the original code still compiles.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100