rust-lang / rust-lang/rust-clippy

Wrongly suggested expression simplification inside match-like expression where drop behavior is different

Open
#10,922 3 comments 0 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

Values X in matched expressions in match X { ... }, while let ... = X { ... }, if let ... = X { ... } have their lifetime extended until the end of match/while-let/if-let. In this context, simplification of some expressions such as (|| code)() into code produces semantically different results - values in the first being dropped at the end of the function and not dropped until the end of match/while-let/if-let in the second. Therefore, clippy should be extra careful about proposing simplifications that involve reducing the number of scopes in this context.

Lint Name

redundant_closure_call

Reproducer

I tried this code in clippy 0.1.72 (e6d4725 2023-06-05):

struct NoisyDrop(u8);
impl Drop for NoisyDrop {
    fn drop(&mut self) {
        println!("{}", self.0);
    }
}

fn noise() -> NoisyDrop {
    NoisyDrop(0)
}

fn main() {
    println!("before match 1");
    match noise().0 {
        0 => {
            println!("inside match 1");
        }
        _ => {
            unreachable!()
        }
    };

    println!("before match 2");
    match (|| noise().0)() {
        0 => {
            println!("inside match 2");
        }
        _ => {
            unreachable!()
        }
    };
}

I saw this happen:

warning: try not to call a closure in the expression where it is declared
  --> src/main.rs:21:11
   |
21 |     match (|| noise().0)() {
   |           ^^^^^^^^^^^^^^^^ help: try doing something like: `noise().0`
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_call
   = note: `#[warn(clippy::redundant_closure_call)]` on by default

I expected to see this happen:
No suggestion at all.

Version
rustc 1.72.0-nightly (e6d4725c7 2023-06-05)
binary: rustc
commit-hash: e6d4725c76f3b526c74454bc51afdf6daf133506
commit-date: 2023-06-05
host: x86_64-unknown-linux-gnu
release: 1.72.0-nightly
LLVM version: 16.0.4
Additional Labels

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 by locating the redundant_closure_call lint implementation and its existing tests, then reproduce the reported match, while-let, and if-let cases. Check how the lint determines whether to suggest replacing a closure call, and add regression coverage showing that no suggestion is emitted when scope or drop behavior changes. Done means the reproducer no longer receives a suggestion without breaking existing cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.