From 1288b80affc300819a38cf56de9d4776f3e50e1f Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Sat, 18 Dec 2021 20:07:58 +0800
Subject: [PATCH] rustc_metadata: Optimize and document module children
 decoding

---
 clippy_utils/src/lib.rs | 31 +++++++++++++++++++------------
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 9179e67c4f4..bd6851d1fbb 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -82,7 +82,6 @@ use rustc_hir::{
     TraitItemKind, TraitRef, TyKind, UnOp, ArrayLen
 };
 use rustc_lint::{LateContext, Level, Lint, LintContext};
-use rustc_middle::hir::exports::Export;
 use rustc_middle::hir::map::Map;
 use rustc_middle::hir::place::PlaceBase;
 use rustc_middle::ty as rustc_ty;
@@ -523,10 +522,21 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
             }
         };
     }
-    fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Option<&'tcx Export> {
-        tcx.item_children(def_id)
-            .iter()
-            .find(|item| item.ident.name.as_str() == name)
+    fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Option<Res> {
+        match tcx.def_kind(def_id) {
+            DefKind::Mod | DefKind::Enum | DefKind::Trait => tcx
+                .item_children(def_id)
+                .iter()
+                .find(|item| item.ident.name.as_str() == name)
+                .map(|child| child.res.expect_non_local()),
+            DefKind::Impl => tcx
+                .associated_item_def_ids(def_id)
+                .iter()
+                .copied()
+                .find(|assoc_def_id| tcx.item_name(*assoc_def_id).as_str() == name)
+                .map(|assoc_def_id| Res::Def(tcx.def_kind(assoc_def_id), assoc_def_id)),
+            _ => None,
+        }
     }
 
     let (krate, first, path) = match *path {
@@ -543,15 +553,12 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
     let last = path
         .iter()
         .copied()
-        // `get_def_path` seems to generate these empty segments for extern blocks.
-        // We can just ignore them.
-        .filter(|segment| !segment.is_empty())
         // for each segment, find the child item
-        .try_fold(first, |item, segment| {
-            let def_id = item.res.def_id();
+        .try_fold(first, |res, segment| {
+            let def_id = res.def_id();
             if let Some(item) = item_child_by_name(tcx, def_id, segment) {
                 Some(item)
-            } else if matches!(item.res, Res::Def(DefKind::Enum | DefKind::Struct, _)) {
+            } else if matches!(res, Res::Def(DefKind::Enum | DefKind::Struct, _)) {
                 // it is not a child item so check inherent impl items
                 tcx.inherent_impls(def_id)
                     .iter()
@@ -560,7 +567,7 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
                 None
             }
         });
-    try_res!(last).res.expect_non_local()
+    try_res!(last).expect_non_local()
 }
 
 /// Convenience function to get the `DefId` of a trait by path.