rust-lang / rust-lang/rust-clippy

Another let_and_return false positive

Open
#8,114 0 comments 6 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

C-bug I-false-positive I-suggestion-causes-error
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.