about summary refs log tree commit diff
path: root/clippy_lints/src/utils/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'clippy_lints/src/utils/mod.rs')
-rw-r--r--clippy_lints/src/utils/mod.rs25
1 files changed, 25 insertions, 0 deletions
diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs
index 8297b9d128d..a1ecca0961a 100644
--- a/clippy_lints/src/utils/mod.rs
+++ b/clippy_lints/src/utils/mod.rs
@@ -268,6 +268,7 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Option<def::Res> {
             krate: *krate,
             index: CRATE_DEF_INDEX,
         };
+        let mut current_item = None;
         let mut items = cx.tcx.item_children(krate);
         let mut path_it = path.iter().skip(1).peekable();
 
@@ -277,6 +278,12 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Option<def::Res> {
                 None => return None,
             };
 
+            // `get_def_path` seems to generate these empty segments for extern blocks.
+            // We can just ignore them.
+            if segment.is_empty() {
+                continue;
+            }
+
             let result = SmallVec::<[_; 8]>::new();
             for item in mem::replace(&mut items, cx.tcx.arena.alloc_slice(&result)).iter() {
                 if item.ident.name.as_str() == *segment {
@@ -284,10 +291,28 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Option<def::Res> {
                         return Some(item.res);
                     }
 
+                    current_item = Some(item);
                     items = cx.tcx.item_children(item.res.def_id());
                     break;
                 }
             }
+
+            // The segment isn't a child_item.
+            // Try to find it under an inherent impl.
+            if_chain! {
+                if path_it.peek().is_none();
+                if let Some(current_item) = current_item;
+                let item_def_id = current_item.res.def_id();
+                if cx.tcx.def_kind(item_def_id) == DefKind::Struct;
+                then {
+                    // Bad `find_map` suggestion. See #4193.
+                    #[allow(clippy::find_map)]
+                    return cx.tcx.inherent_impls(item_def_id).iter()
+                        .flat_map(|&impl_def_id| cx.tcx.item_children(impl_def_id))
+                        .find(|item| item.ident.name.as_str() == *segment)
+                        .map(|item| item.res);
+                }
+            }
         }
     } else {
         None