From b73b4de982a16e8819e804cb648ff3ea63d22028 Mon Sep 17 00:00:00 2001 From: Miguel Guarniz Date: Sun, 3 Apr 2022 15:50:33 -0400 Subject: [PATCH] Refactor HIR item-like traversal (part 1) - Create hir_crate_items query which traverses tcx.hir_crate(()).owners to return a hir::ModuleItems - use tcx.hir_crate_items in tcx.hir().items() to return an iterator of hir::ItemId - add par_items(impl Fn(hir::ItemId)) to traverse all items in parallel Signed-off-by: Miguel Guarniz --- compiler/rustc_middle/src/hir/map/mod.rs | 89 ++++++++++++++++--- compiler/rustc_middle/src/hir/mod.rs | 1 + compiler/rustc_middle/src/query/mod.rs | 7 ++ compiler/rustc_middle/src/ty/print/pretty.rs | 3 +- .../clippy_lints/src/same_name_method.rs | 3 +- .../clippy/tests/ui/same_name_method.stderr | 26 +++--- 6 files changed, 100 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 561653f3bebf..79bbf5915349 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -18,7 +18,6 @@ use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use rustc_target::spec::abi::Abi; -use std::collections::VecDeque; fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> { match node { @@ -159,12 +158,12 @@ impl<'hir> Map<'hir> { } } - pub fn items(self) -> impl Iterator> + 'hir { - let krate = self.krate(); - krate.owners.iter().filter_map(|owner| match owner.as_owner()?.node() { - OwnerNode::Item(item) => Some(item), - _ => None, - }) + pub fn items(self) -> impl Iterator + 'hir { + self.tcx.hir_crate_items(()).items.iter().map(|id| *id) + } + + pub fn par_items(self, f: impl Fn(ItemId) + Sync + Send) { + par_for_each_in(self.tcx.hir_crate_items(()).items.to_vec(), f); } pub fn def_key(self, def_id: LocalDefId) -> DefKey { @@ -677,13 +676,9 @@ impl<'hir> Map<'hir> { } pub fn for_each_module(self, f: impl Fn(LocalDefId)) { - let mut queue = VecDeque::new(); - queue.push_back(CRATE_DEF_ID); - - while let Some(id) = queue.pop_front() { - f(id); - let items = self.tcx.hir_module_items(id); - queue.extend(items.submodules.iter().copied()) + let crate_items = self.tcx.hir_crate_items(()); + for module in crate_items.submodules.iter() { + f(*module) } } @@ -1310,3 +1305,69 @@ pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalDefId) -> Module } } } + +pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems { + let mut collector = CrateCollector { + tcx, + submodules: Vec::default(), + items: Vec::default(), + trait_items: Vec::default(), + impl_items: Vec::default(), + foreign_items: Vec::default(), + }; + + tcx.hir().walk_toplevel_module(&mut collector); + + let CrateCollector { submodules, items, trait_items, impl_items, foreign_items, .. } = + collector; + + return ModuleItems { + submodules: submodules.into_boxed_slice(), + items: items.into_boxed_slice(), + trait_items: trait_items.into_boxed_slice(), + impl_items: impl_items.into_boxed_slice(), + foreign_items: foreign_items.into_boxed_slice(), + }; + + struct CrateCollector<'tcx> { + tcx: TyCtxt<'tcx>, + submodules: Vec, + items: Vec, + trait_items: Vec, + impl_items: Vec, + foreign_items: Vec, + } + + impl<'hir> Visitor<'hir> for CrateCollector<'hir> { + type NestedFilter = nested_filter::All; + + fn nested_visit_map(&mut self) -> Self::Map { + self.tcx.hir() + } + + fn visit_item(&mut self, item: &'hir Item<'hir>) { + self.items.push(item.item_id()); + intravisit::walk_item(self, item) + } + + fn visit_mod(&mut self, m: &'hir Mod<'hir>, _s: Span, n: HirId) { + self.submodules.push(n.owner); + intravisit::walk_mod(self, m, n); + } + + fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) { + self.foreign_items.push(item.foreign_item_id()); + intravisit::walk_foreign_item(self, item) + } + + fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) { + self.trait_items.push(item.trait_item_id()); + intravisit::walk_trait_item(self, item) + } + + fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) { + self.impl_items.push(item.impl_item_id()); + intravisit::walk_impl_item(self, item) + } + } +} diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index a9e22d16ee05..fcce2d005d79 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -68,6 +68,7 @@ pub fn provide(providers: &mut Providers) { hir.get_module_parent_node(hir.local_def_id_to_hir_id(id)) }; providers.hir_crate = |tcx, ()| tcx.untracked_crate; + providers.hir_crate_items = map::hir_crate_items; providers.crate_hash = map::crate_hash; providers.hir_module_items = map::hir_module_items; providers.hir_owner = |tcx, id| { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 89761bf4e27a..6733e0f7f3c7 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -45,6 +45,13 @@ rustc_queries! { desc { "get the crate HIR" } } + /// All items in the crate. + query hir_crate_items(_: ()) -> rustc_middle::hir::ModuleItems { + storage(ArenaCacheSelector<'tcx>) + eval_always + desc { "get HIR crate items" } + } + /// The items in a module. /// /// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`. diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 9a9c529f2455..61f078c0e482 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2682,7 +2682,8 @@ define_print_and_forward_display! { fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, Namespace, DefId)) { // Iterate all local crate items no matter where they are defined. let hir = tcx.hir(); - for item in hir.items() { + for id in hir.items() { + let item = hir.item(id); if item.ident.name.as_str().is_empty() || matches!(item.kind, ItemKind::Use(_, _)) { continue; } diff --git a/src/tools/clippy/clippy_lints/src/same_name_method.rs b/src/tools/clippy/clippy_lints/src/same_name_method.rs index 22b458969551..c76061867145 100644 --- a/src/tools/clippy/clippy_lints/src/same_name_method.rs +++ b/src/tools/clippy/clippy_lints/src/same_name_method.rs @@ -50,7 +50,8 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod { fn check_crate_post(&mut self, cx: &LateContext<'tcx>) { let mut map = FxHashMap::::default(); - for item in cx.tcx.hir().items() { + for id in cx.tcx.hir().items() { + let item = cx.tcx.hir().item(id); if let ItemKind::Impl(Impl { items, of_trait, diff --git a/src/tools/clippy/tests/ui/same_name_method.stderr b/src/tools/clippy/tests/ui/same_name_method.stderr index c32c3dd9880f..cf06eb32e0c7 100644 --- a/src/tools/clippy/tests/ui/same_name_method.stderr +++ b/src/tools/clippy/tests/ui/same_name_method.stderr @@ -11,6 +11,19 @@ note: existing `foo` defined here LL | fn foo() {} | ^^^^^^^^^^^ +error: method's name is the same as an existing method in a trait + --> $DIR/same_name_method.rs:34:13 + | +LL | fn clone() {} + | ^^^^^^^^^^^^^ + | +note: existing `clone` defined here + --> $DIR/same_name_method.rs:30:18 + | +LL | #[derive(Clone)] + | ^^^^^ + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) + error: method's name is the same as an existing method in a trait --> $DIR/same_name_method.rs:44:13 | @@ -47,18 +60,5 @@ note: existing `foo` defined here LL | impl T1 for S {} | ^^^^^^^^^^^^^^^^ -error: method's name is the same as an existing method in a trait - --> $DIR/same_name_method.rs:34:13 - | -LL | fn clone() {} - | ^^^^^^^^^^^^^ - | -note: existing `clone` defined here - --> $DIR/same_name_method.rs:30:18 - | -LL | #[derive(Clone)] - | ^^^^^ - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) - error: aborting due to 5 previous errors