From 1288b80affc300819a38cf56de9d4776f3e50e1f Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov 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 { + 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.