From 326139f98a4c5f59ba734cce447beb2bb5c985ad Mon Sep 17 00:00:00 2001 From: jasminelcy <2473533997@qq.com> Date: Fri, 17 Apr 2026 03:22:48 +0800 Subject: [PATCH] Don't suggest `collapsible_match` guard when condition mutates pattern binding When `mutated_variables` returns `None` (cannot determine mutations), `pat_bindings_moved_or_mutated` silently ignored the result instead of conservatively bailing out. This caused the lint to suggest match guards for expressions that require mutable access to pattern bindings, which is forbidden in guards. Fixes #16864 --- clippy_lints/src/matches/collapsible_match.rs | 7 +++--- tests/ui/collapsible_match.rs | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/matches/collapsible_match.rs b/clippy_lints/src/matches/collapsible_match.rs index cb784d1ff660..9dc2454caab1 100644 --- a/clippy_lints/src/matches/collapsible_match.rs +++ b/clippy_lints/src/matches/collapsible_match.rs @@ -275,9 +275,10 @@ fn pat_bindings_moved_or_mutated<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>, } let mut candidates = delegate.moved; - if let Some(mutated) = mutated_variables(expr, cx) { - candidates.extend(mutated); - } + let Some(mutated) = mutated_variables(expr, cx) else { + return true; + }; + candidates.extend(mutated); !pat.walk_short(|pat| { if let PatKind::Binding(_, hir_id, ..) = pat.kind diff --git a/tests/ui/collapsible_match.rs b/tests/ui/collapsible_match.rs index 98f2fcfdf479..d2f8c0d88055 100644 --- a/tests/ui/collapsible_match.rs +++ b/tests/ui/collapsible_match.rs @@ -444,3 +444,28 @@ fn issue16705(x: Option) { _ => false, }; } + +// issue #16864: don't suggest guard when condition mutates pattern binding +fn issue16864() -> Option { + struct Foo(u32); + + impl Foo { + fn mutates(&mut self) -> bool { + self.0 += 1; + self.0.is_multiple_of(2) + } + } + + let mut value: Option = Some(Foo(42)); + // Should NOT lint: inner.mutates() requires &mut self, + // but variables are immutable in match guards. + match &mut value { + Some(inner) => { + if inner.mutates() { + return Some(inner.0); + } + }, + _ => {}, + } + None +}