From 75abcda35dd38ef7f5c73b3a78ab5cf3bae044a7 Mon Sep 17 00:00:00 2001 From: Gri-ffin Date: Sat, 11 Jul 2026 14:44:54 +0100 Subject: [PATCH] fix if_not_else firing on macro expanded conditions --- clippy_lints/src/if_not_else.rs | 3 +- tests/ui/if_not_else.fixed | 68 +++++++++++++++++++++++++++++++++ tests/ui/if_not_else.rs | 68 +++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index ea1992d47131..9b904699b9af 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -52,6 +52,7 @@ impl LateLintPass<'_> for IfNotElse { fn check_expr(&mut self, cx: &LateContext<'_>, e: &Expr<'_>) { if let ExprKind::If(cond, cond_inner, Some(els)) = e.kind && let ExprKind::Block(..) = els.kind + && !cond.span.from_expansion() { let (msg, help) = match cond.kind { ExprKind::Unary(UnOp::Not, _) => ( @@ -61,7 +62,7 @@ impl LateLintPass<'_> for IfNotElse { // Don't lint on `… != 0`, as these are likely to be bit tests. // For example, `if foo & 0x0F00 != 0 { … } else { … }` is already in the "proper" order. ExprKind::Binary(op, _, rhs) - if op.node == BinOpKind::Ne && !is_zero_integer_const(cx, rhs, e.span.ctxt()) => + if op.node == BinOpKind::Ne && !is_zero_integer_const(cx, rhs, cond.span.ctxt()) => { ( "unnecessary `!=` operation", diff --git a/tests/ui/if_not_else.fixed b/tests/ui/if_not_else.fixed index a29847f0cf97..9c01cb62ac77 100644 --- a/tests/ui/if_not_else.fixed +++ b/tests/ui/if_not_else.fixed @@ -93,3 +93,71 @@ fn issue15924() { println!(":)"); } } + +mod issue17373 { + macro_rules! ht_is_packed { + ($ht:expr) => { + ($ht).u & 4 != 0 + }; + } + struct HashTable { + u: u32, + } + impl HashTable { + fn check(&mut self) { + if ht_is_packed!(self) { + println!("Packed"); + } else { + println!("Not packed"); + } + } + } + + macro_rules! is_active { + ($x:expr) => { + ($x).state != 3 + }; + } + struct Widget { + state: u32, + } + impl Widget { + fn check(&self) { + if is_active!(self) { + println!("active"); + } else { + println!("inactive"); + } + } + } + + macro_rules! not_ready { + ($x:expr) => { + !($x).ready + }; + } + struct Task { + ready: bool, + } + impl Task { + fn check(&self) { + if not_ready!(self) { + println!("waiting"); + } else { + println!("go"); + } + } + } + + macro_rules! wrap_if { + ($cond:expr, $t:block, $e:block) => { + if $cond $t else $e + }; + } + fn wrap_if_macro() { + let x = 0; + fn a() {} + fn b() {} + wrap_if!(x != 0, { a() }, { b() }); + } +} diff --git a/tests/ui/if_not_else.rs b/tests/ui/if_not_else.rs index 4ae11d6ad90e..9d7da2dac37a 100644 --- a/tests/ui/if_not_else.rs +++ b/tests/ui/if_not_else.rs @@ -93,3 +93,71 @@ fn issue15924() { println!(":("); } } + +mod issue17373 { + macro_rules! ht_is_packed { + ($ht:expr) => { + ($ht).u & 4 != 0 + }; + } + struct HashTable { + u: u32, + } + impl HashTable { + fn check(&mut self) { + if ht_is_packed!(self) { + println!("Packed"); + } else { + println!("Not packed"); + } + } + } + + macro_rules! is_active { + ($x:expr) => { + ($x).state != 3 + }; + } + struct Widget { + state: u32, + } + impl Widget { + fn check(&self) { + if is_active!(self) { + println!("active"); + } else { + println!("inactive"); + } + } + } + + macro_rules! not_ready { + ($x:expr) => { + !($x).ready + }; + } + struct Task { + ready: bool, + } + impl Task { + fn check(&self) { + if not_ready!(self) { + println!("waiting"); + } else { + println!("go"); + } + } + } + + macro_rules! wrap_if { + ($cond:expr, $t:block, $e:block) => { + if $cond $t else $e + }; + } + fn wrap_if_macro() { + let x = 0; + fn a() {} + fn b() {} + wrap_if!(x != 0, { a() }, { b() }); + } +}