From 95cd5e38f70110735c8c1098d7fba92a6d6c4b73 Mon Sep 17 00:00:00 2001 From: llogiq Date: Fri, 5 Dec 2025 18:51:48 +0000 Subject: [PATCH] Fix `panicking_unwrap` FP on field access with implicit deref (#16196) Closes rust-lang/rust-clippy#16188 ---- changelog: [`panicking_unwrap`] fix FP on field access with implicit deref --- src/tools/clippy/clippy_lints/src/unwrap.rs | 9 +++++++-- .../ui/checked_unwrap/simple_conditionals.rs | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs index 8ed3df8731b3f..a95f2b681add0 100644 --- a/src/tools/clippy/clippy_lints/src/unwrap.rs +++ b/src/tools/clippy/clippy_lints/src/unwrap.rs @@ -180,14 +180,19 @@ impl Local { field_indices, .. } => { + let field_projections = place + .projections + .iter() + .filter(|proj| matches!(proj.kind, ProjectionKind::Field(_, _))) + .collect::>(); is_potentially_local_place(*local_id, place) // If there were projections other than field projections, err on the side of caution and say that they // _might_ be mutating something. // // The reason we use `<=` and not `==` is that a mutation of `struct` or `struct.field1` should count as // mutation of the child fields such as `struct.field1.field2` - && place.projections.len() <= field_indices.len() - && iter::zip(&place.projections, field_indices.iter().copied().rev()).all(|(proj, field_idx)| { + && field_projections.len() <= field_indices.len() + && iter::zip(&field_projections, field_indices.iter().copied().rev()).all(|(proj, field_idx)| { match proj.kind { ProjectionKind::Field(f_idx, _) => f_idx == field_idx, // If this is a projection we don't expect, it _might_ be mutating something diff --git a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs index c6476a7507a1d..bab20b091d389 100644 --- a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs +++ b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs @@ -472,3 +472,22 @@ fn issue15321() { //~^ unnecessary_unwrap } } + +mod issue16188 { + struct Foo { + value: Option, + } + + impl Foo { + pub fn bar(&mut self) { + let print_value = |v: i32| { + println!("{}", v); + }; + + if self.value.is_none() { + self.value = Some(10); + print_value(self.value.unwrap()); + } + } + } +}