Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gather module items after lowering. #88703

Merged
merged 3 commits into from
Sep 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,6 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
self.lctx.with_parent_item_lifetime_defs(hir_id, |this| {
let this = &mut ItemLowerer { lctx: this };
match item.kind {
ItemKind::Mod(..) => {
let def_id = this.lctx.lower_node_id(item.id).expect_owner();
let old_current_module = mem::replace(&mut this.lctx.current_module, def_id);
visit::walk_item(this, item);
this.lctx.current_module = old_current_module;
}
ItemKind::Impl(box ImplKind { ref of_trait, .. }) => {
this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item));
}
Expand Down
19 changes: 2 additions & 17 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,6 @@ struct LoweringContext<'a, 'hir: 'a> {
owners: IndexVec<LocalDefId, Option<hir::OwnerNode<'hir>>>,
bodies: BTreeMap<hir::BodyId, hir::Body<'hir>>,

modules: BTreeMap<LocalDefId, hir::ModuleItems>,

generator_kind: Option<hir::GeneratorKind>,

attrs: BTreeMap<hir::HirId, &'hir [Attribute]>,
Expand Down Expand Up @@ -152,8 +150,6 @@ struct LoweringContext<'a, 'hir: 'a> {
/// vector.
in_scope_lifetimes: Vec<ParamName>,

current_module: LocalDefId,

current_hir_id_owner: (LocalDefId, u32),
item_local_id_counters: NodeMap<u32>,
node_id_to_hir_id: IndexVec<NodeId, Option<hir::HirId>>,
Expand Down Expand Up @@ -327,15 +323,13 @@ pub fn lower_crate<'a, 'hir>(
arena,
owners: IndexVec::default(),
bodies: BTreeMap::new(),
modules: BTreeMap::new(),
attrs: BTreeMap::default(),
catch_scope: None,
loop_scope: None,
is_in_loop_condition: false,
is_in_trait_impl: false,
is_in_dyn_type: false,
anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough,
current_module: CRATE_DEF_ID,
current_hir_id_owner: (CRATE_DEF_ID, 0),
item_local_id_counters: Default::default(),
node_id_to_hir_id: IndexVec::new(),
Expand Down Expand Up @@ -508,13 +502,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}

let krate = hir::Crate {
owners: self.owners,
bodies: self.bodies,
modules: self.modules,
trait_map,
attrs: self.attrs,
};
let krate =
hir::Crate { owners: self.owners, bodies: self.bodies, trait_map, attrs: self.attrs };
self.arena.alloc(krate)
}

Expand All @@ -523,7 +512,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let item = self.arena.alloc(item);
self.owners.ensure_contains_elem(id.def_id, || None);
self.owners[id.def_id] = Some(hir::OwnerNode::Item(item));
self.modules.entry(self.current_module).or_default().items.insert(id);
id
}

Expand All @@ -532,7 +520,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let item = self.arena.alloc(item);
self.owners.ensure_contains_elem(id.def_id, || None);
self.owners[id.def_id] = Some(hir::OwnerNode::ForeignItem(item));
self.modules.entry(self.current_module).or_default().foreign_items.insert(id);
id
}

Expand All @@ -541,7 +528,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let item = self.arena.alloc(item);
self.owners.ensure_contains_elem(id.def_id, || None);
self.owners[id.def_id] = Some(hir::OwnerNode::ImplItem(item));
self.modules.entry(self.current_module).or_default().impl_items.insert(id);
id
}

Expand All @@ -550,7 +536,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let item = self.arena.alloc(item);
self.owners.ensure_contains_elem(id.def_id, || None);
self.owners[id.def_id] = Some(hir::OwnerNode::TraitItem(item));
self.modules.entry(self.current_module).or_default().trait_items.insert(id);
id
}

Expand Down
16 changes: 1 addition & 15 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use rustc_target::asm::InlineAsmRegOrRegClass;
use rustc_target::spec::abi::Abi;

use smallvec::SmallVec;
use std::collections::{BTreeMap, BTreeSet};
use std::collections::BTreeMap;
use std::fmt;

#[derive(Copy, Clone, Encodable, HashStable_Generic)]
Expand Down Expand Up @@ -653,16 +653,6 @@ pub struct WhereEqPredicate<'hir> {
pub rhs_ty: &'hir Ty<'hir>,
}

#[derive(Default, Encodable, Debug, HashStable_Generic)]
pub struct ModuleItems {
// Use BTreeSets here so items are in the same order as in the
// list of all items in Crate
pub items: BTreeSet<ItemId>,
pub trait_items: BTreeSet<TraitItemId>,
pub impl_items: BTreeSet<ImplItemId>,
pub foreign_items: BTreeSet<ForeignItemId>,
}

/// The top-level data structure that stores the entire contents of
/// the crate currently being compiled.
///
Expand All @@ -674,10 +664,6 @@ pub struct Crate<'hir> {
pub owners: IndexVec<LocalDefId, Option<OwnerNode<'hir>>>,
pub bodies: BTreeMap<BodyId, Body<'hir>>,

/// A list of modules written out in the order in which they
/// appear in the crate. This includes the main crate module.
pub modules: BTreeMap<LocalDefId, ModuleItems>,

/// Map indicating what traits are in scope for places where this
/// is relevant; generated by resolve.
pub trait_map: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Box<[TraitCandidate]>>>,
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rustc_borrowck as mir_borrowck;
use rustc_codegen_ssa::back::link::emit_metadata;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::parallel;
use rustc_data_structures::sync::{par_iter, Lrc, OnceCell, ParallelIterator, WorkerLocal};
use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_errors::{ErrorReported, PResult};
use rustc_expand::base::ExtCtxt;
Expand Down Expand Up @@ -861,7 +861,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
CStore::from_tcx(tcx).report_unused_deps(tcx);
},
{
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
tcx.hir().par_for_each_module(|module| {
tcx.ensure().check_mod_loops(module);
tcx.ensure().check_mod_attrs(module);
tcx.ensure().check_mod_naked_functions(module);
Expand Down Expand Up @@ -893,7 +893,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
},
{
sess.time("liveness_and_intrinsic_checking", || {
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
tcx.hir().par_for_each_module(|module| {
// this must run before MIR dump, because
// "not all control paths return a value" is reported here.
//
Expand Down Expand Up @@ -963,7 +963,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
},
{
sess.time("privacy_checking_modules", || {
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
tcx.hir().par_for_each_module(|module| {
tcx.ensure().check_mod_privacy(module);
});
});
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_lint/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore};
use rustc_ast as ast;
use rustc_data_structures::sync::{join, par_iter, ParallelIterator};
use rustc_data_structures::sync::join;
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit as hir_visit;
Expand Down Expand Up @@ -501,9 +501,7 @@ pub fn check_crate<'tcx, T: LateLintPass<'tcx>>(
|| {
tcx.sess.time("module_lints", || {
// Run per-module lints
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
tcx.ensure().lint_mod(module);
});
tcx.hir().par_for_each_module(|module| tcx.ensure().lint_mod(module));
});
},
);
Expand Down
109 changes: 104 additions & 5 deletions compiler/rustc_middle/src/hir/map/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use self::collector::NodeCollector;

use crate::hir::{AttributeMap, IndexedHir, Owner};
use crate::hir::{AttributeMap, IndexedHir, ModuleItems, Owner};
use crate::ty::TyCtxt;
use rustc_ast as ast;
use rustc_data_structures::fingerprint::Fingerprint;
Expand All @@ -19,6 +19,7 @@ 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;

pub mod blocks;
mod collector;
Expand Down Expand Up @@ -541,23 +542,55 @@ impl<'hir> Map<'hir> {
{
let module = self.tcx.hir_module_items(module);

for id in &module.items {
for id in module.items.iter() {
visitor.visit_item(self.item(*id));
}

for id in &module.trait_items {
for id in module.trait_items.iter() {
visitor.visit_trait_item(self.trait_item(*id));
}

for id in &module.impl_items {
for id in module.impl_items.iter() {
visitor.visit_impl_item(self.impl_item(*id));
}

for id in &module.foreign_items {
for id in module.foreign_items.iter() {
visitor.visit_foreign_item(self.foreign_item(*id));
}
}

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())
}
}

#[cfg(not(parallel_compiler))]
#[inline]
pub fn par_for_each_module(&self, f: impl Fn(LocalDefId)) {
self.for_each_module(f)
}

#[cfg(parallel_compiler)]
pub fn par_for_each_module(&self, f: impl Fn(LocalDefId) + Sync) {
use rustc_data_structures::sync::{par_iter, ParallelIterator};
par_iter_submodules(self.tcx, CRATE_DEF_ID, &f);

fn par_iter_submodules<F>(tcx: TyCtxt<'_>, module: LocalDefId, f: &F)
where
F: Fn(LocalDefId) + Sync,
{
(*f)(module);
let items = tcx.hir_module_items(module);
par_iter(&items.submodules[..]).for_each(|&sm| par_iter_submodules(tcx, sm, f));
}
}

/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
/// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
pub fn parent_iter(&self, current_id: HirId) -> ParentHirIterator<'_, 'hir> {
Expand Down Expand Up @@ -1118,3 +1151,69 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String {
None => format!("unknown node{}", id_str),
}
}

pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalDefId) -> ModuleItems {
let mut collector = ModuleCollector {
tcx,
submodules: Vec::default(),
items: Vec::default(),
trait_items: Vec::default(),
impl_items: Vec::default(),
foreign_items: Vec::default(),
};

let (hir_mod, span, hir_id) = tcx.hir().get_module(module_id);
collector.visit_mod(hir_mod, span, hir_id);

let ModuleCollector { 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 ModuleCollector<'tcx> {
tcx: TyCtxt<'tcx>,
submodules: Vec<LocalDefId>,
items: Vec<ItemId>,
trait_items: Vec<TraitItemId>,
impl_items: Vec<ImplItemId>,
foreign_items: Vec<ForeignItemId>,
}

impl<'hir> Visitor<'hir> for ModuleCollector<'hir> {
type Map = Map<'hir>;

fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
intravisit::NestedVisitorMap::All(self.tcx.hir())
}

fn visit_item(&mut self, item: &'hir Item<'hir>) {
self.items.push(item.item_id());
if let ItemKind::Mod(..) = item.kind {
// If this declares another module, do not recurse inside it.
self.submodules.push(item.def_id);
} else {
intravisit::walk_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)
}

fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) {
self.foreign_items.push(item.foreign_item_id());
intravisit::walk_foreign_item(self, item)
}
}
}
13 changes: 12 additions & 1 deletion compiler/rustc_middle/src/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,17 @@ impl<'tcx> AttributeMap<'tcx> {
}
}

/// Gather the LocalDefId for each item-like within a module, including items contained within
/// bodies. The Ids are in visitor order. This is used to partition a pass between modules.
#[derive(Debug, HashStable)]
pub struct ModuleItems {
submodules: Box<[LocalDefId]>,
items: Box<[ItemId]>,
trait_items: Box<[TraitItemId]>,
impl_items: Box<[ImplItemId]>,
foreign_items: Box<[ForeignItemId]>,
}

impl<'tcx> TyCtxt<'tcx> {
#[inline(always)]
pub fn hir(self) -> map::Map<'tcx> {
Expand All @@ -140,7 +151,7 @@ pub fn provide(providers: &mut Providers) {
providers.hir_crate = |tcx, ()| tcx.untracked_crate;
providers.index_hir = map::index_hir;
providers.crate_hash = map::crate_hash;
providers.hir_module_items = |tcx, id| &tcx.untracked_crate.modules[&id];
providers.hir_module_items = map::hir_module_items;
providers.hir_owner = |tcx, id| {
let owner = tcx.index_hir(()).map[id].as_ref()?;
let node = owner.nodes[ItemLocalId::new(0)].as_ref().unwrap().node;
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#![feature(discriminant_kind)]
#![feature(exhaustive_patterns)]
#![feature(if_let_guard)]
#![feature(map_first_last)]
#![feature(never_type)]
#![feature(extern_types)]
#![feature(new_uninit)]
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ rustc_queries! {
///
/// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`.
/// Avoid calling this query directly.
query hir_module_items(key: LocalDefId) -> &'tcx hir::ModuleItems {
eval_always
query hir_module_items(key: LocalDefId) -> rustc_middle::hir::ModuleItems {
storage(ArenaCacheSelector<'tcx>)
desc { |tcx| "HIR module items in `{}`", tcx.def_path_str(key.to_def_id()) }
}

Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_passes/src/hir_id_validator.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator};
use rustc_data_structures::sync::Lock;
use rustc_hir as hir;
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_INDEX};
use rustc_hir::intravisit;
Expand All @@ -18,9 +18,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
let errors = Lock::new(Vec::new());
let hir_map = tcx.hir();

par_iter(&hir_map.krate().modules).for_each(|(&module_id, _)| {
hir_map.par_for_each_module(|module_id| {
hir_map
.visit_item_likes_in_module(module_id, &mut OuterVisitor { hir_map, errors: &errors });
.visit_item_likes_in_module(module_id, &mut OuterVisitor { hir_map, errors: &errors })
});

let errors = errors.into_inner();
Expand Down
Loading