rust-lang / rust-clippy

A bunch of lints to catch common mistakes and improve your Rust code. Book: https://doc.rust-lang.org/clippy/
https://rust-lang.github.io/rust-clippy/
Other
11.41k stars 1.54k forks source link

`clippy::question_mark` ignores `#[cfg]`-ed out statements in `let-else` #13642

Open GoldsteinE opened 2 hours ago

GoldsteinE commented 2 hours ago

Summary

else block in let-else can have different behaviour depending on build configuration. Clippy ignores it and suggests replacing let-else block with ?, completely removing #[cfg]-ed out logic.

As Clippy can’t look inside #[cfg]-ed out statements, probably it shouldn’t ever suggest removing such code.

Lint Name

clippy::question_mark

Reproducer

I tried this code:

fn returns_option() -> Option<u8> {
    None
}

pub fn check() -> Option<u8> {
    let Some(x) = returns_option() else {
        #[cfg(any())]
        panic!();

        #[cfg(not(any()))]
        return None;
    };
    Some(x)
}

I saw this happen:

  --> src/lib.rs:6:5
   |
6  | /     let Some(x) = returns_option() else {
7  | |         #[cfg(any())]
8  | |         panic!();
...  |
11 | |         return None;
12 | |     };
   | |______^ help: replace it with: `let x = returns_option()?;`
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#question_mark
   = note: `#[warn(clippy::question_mark)]` on by default

I expected to see this happen: (no output).

Version

rustc 1.79.0 (129f3b996 2024-06-10) binary: rustc commit-hash: 129f3b9964af4d4a709d1383930ade12dfe7c081 commit-date: 2024-06-10 host: x86_64-unknown-linux-gnu release: 1.79.0 LLVM version: 18.1.7

Additional Labels

@rustbot label +I-suggestion-causes-bug

GoldsteinE commented 2 hours ago

Weirdly, adding #[allow(clippy::question_mark)] before let doesn’t make the warning go away.