Skip to content

Store HIR ForeignItem in a side table #79318

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

Merged
merged 7 commits into from
Nov 27, 2020
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
30 changes: 25 additions & 5 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
items: BTreeSet::new(),
trait_items: BTreeSet::new(),
impl_items: BTreeSet::new(),
foreign_items: BTreeSet::new(),
},
);

Expand Down Expand Up @@ -105,6 +106,18 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {

visit::walk_assoc_item(self, item, ctxt);
}

fn visit_foreign_item(&mut self, item: &'a ForeignItem) {
self.lctx.allocate_hir_id_counter(item.id);
self.lctx.with_hir_id_owner(item.id, |lctx| {
let hir_item = lctx.lower_foreign_item(item);
let id = hir::ForeignItemId { hir_id: hir_item.hir_id };
lctx.foreign_items.insert(id, hir_item);
lctx.modules.get_mut(&lctx.current_module).unwrap().foreign_items.insert(id);
});

visit::walk_foreign_item(self, item);
}
}

impl<'hir> LoweringContext<'_, 'hir> {
Expand Down Expand Up @@ -304,7 +317,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
})
}
ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)),
ItemKind::ForeignMod(ref nm) => hir::ItemKind::ForeignMod(self.lower_foreign_mod(nm)),
ItemKind::ForeignMod(ref fm) => hir::ItemKind::ForeignMod {
abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)),
items: self
.arena
.alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
},
ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)),
ItemKind::TyAlias(_, ref gen, _, Some(ref ty)) => {
// We lower
Expand Down Expand Up @@ -704,10 +722,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}

fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod<'hir> {
hir::ForeignMod {
abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)),
items: self.arena.alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item(x))),
fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef<'hir> {
hir::ForeignItemRef {
id: hir::ForeignItemId { hir_id: self.lower_node_id(i.id) },
ident: i.ident,
span: i.span,
vis: self.lower_visibility(&i.vis, Some(i.id)),
}
}

Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ struct LoweringContext<'a, 'hir: 'a> {

trait_items: BTreeMap<hir::TraitItemId, hir::TraitItem<'hir>>,
impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem<'hir>>,
foreign_items: BTreeMap<hir::ForeignItemId, hir::ForeignItem<'hir>>,
bodies: BTreeMap<hir::BodyId, hir::Body<'hir>>,
exported_macros: Vec<hir::MacroDef<'hir>>,
non_exported_macro_attrs: Vec<ast::Attribute>,
Expand Down Expand Up @@ -298,6 +299,7 @@ pub fn lower_crate<'a, 'hir>(
items: BTreeMap::new(),
trait_items: BTreeMap::new(),
impl_items: BTreeMap::new(),
foreign_items: BTreeMap::new(),
bodies: BTreeMap::new(),
trait_impls: BTreeMap::new(),
modules: BTreeMap::new(),
Expand Down Expand Up @@ -485,6 +487,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
visit::walk_assoc_item(self, item, ctxt);
}

fn visit_foreign_item(&mut self, item: &'tcx ForeignItem) {
self.lctx.allocate_hir_id_counter(item.id);
visit::walk_foreign_item(self, item);
}

fn visit_ty(&mut self, t: &'tcx Ty) {
match t.kind {
// Mirrors the case in visit::walk_ty
Expand Down Expand Up @@ -548,6 +555,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
items: self.items,
trait_items: self.trait_items,
impl_items: self.impl_items,
foreign_items: self.foreign_items,
bodies: self.bodies,
body_ids,
trait_impls: self.trait_impls,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ macro_rules! arena_types {
[] field_pat: rustc_hir::FieldPat<$tcx>,
[] fn_decl: rustc_hir::FnDecl<$tcx>,
[] foreign_item: rustc_hir::ForeignItem<$tcx>,
[few] foreign_item_ref: rustc_hir::ForeignItemRef<$tcx>,
[] impl_item_ref: rustc_hir::ImplItemRef<$tcx>,
[few] inline_asm: rustc_hir::InlineAsm<$tcx>,
[few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>,
Expand Down
52 changes: 42 additions & 10 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,7 @@ pub struct ModuleItems {
pub items: BTreeSet<HirId>,
pub trait_items: BTreeSet<TraitItemId>,
pub impl_items: BTreeSet<ImplItemId>,
pub foreign_items: BTreeSet<ForeignItemId>,
}

/// A type representing only the top-level module.
Expand Down Expand Up @@ -612,6 +613,7 @@ pub struct Crate<'hir> {

pub trait_items: BTreeMap<TraitItemId, TraitItem<'hir>>,
pub impl_items: BTreeMap<ImplItemId, ImplItem<'hir>>,
pub foreign_items: BTreeMap<ForeignItemId, ForeignItem<'hir>>,
pub bodies: BTreeMap<BodyId, Body<'hir>>,
pub trait_impls: BTreeMap<DefId, Vec<HirId>>,

Expand Down Expand Up @@ -644,6 +646,10 @@ impl Crate<'hir> {
&self.impl_items[&id]
}

pub fn foreign_item(&self, id: ForeignItemId) -> &ForeignItem<'hir> {
&self.foreign_items[&id]
}

pub fn body(&self, id: BodyId) -> &Body<'hir> {
&self.bodies[&id]
}
Expand Down Expand Up @@ -673,6 +679,10 @@ impl Crate<'_> {
for impl_item in self.impl_items.values() {
visitor.visit_impl_item(impl_item);
}

for foreign_item in self.foreign_items.values() {
visitor.visit_foreign_item(foreign_item);
}
}

/// A parallel version of `visit_all_item_likes`.
Expand All @@ -695,6 +705,11 @@ impl Crate<'_> {
par_for_each_in(&self.impl_items, |(_, impl_item)| {
visitor.visit_impl_item(impl_item);
});
},
{
par_for_each_in(&self.foreign_items, |(_, foreign_item)| {
visitor.visit_foreign_item(foreign_item);
});
}
);
}
Expand Down Expand Up @@ -1840,7 +1855,7 @@ pub struct FnSig<'hir> {
}

// The bodies for items are stored "out of line", in a separate
// hashmap in the `Crate`. Here we just record the node-id of the item
// hashmap in the `Crate`. Here we just record the hir-id of the item
// so it can fetched later.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)]
pub struct TraitItemId {
Expand Down Expand Up @@ -1884,7 +1899,7 @@ pub enum TraitItemKind<'hir> {
}

// The bodies for items are stored "out of line", in a separate
// hashmap in the `Crate`. Here we just record the node-id of the item
// hashmap in the `Crate`. Here we just record the hir-id of the item
// so it can fetched later.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)]
pub struct ImplItemId {
Expand Down Expand Up @@ -2269,12 +2284,6 @@ pub struct Mod<'hir> {
pub item_ids: &'hir [ItemId],
}

#[derive(Debug, HashStable_Generic)]
pub struct ForeignMod<'hir> {
pub abi: Abi,
pub items: &'hir [ForeignItem<'hir>],
}

#[derive(Encodable, Debug, HashStable_Generic)]
pub struct GlobalAsm {
pub asm: Symbol,
Expand Down Expand Up @@ -2432,7 +2441,7 @@ impl VariantData<'hir> {
}

// The bodies for items are stored "out of line", in a separate
// hashmap in the `Crate`. Here we just record the node-id of the item
// hashmap in the `Crate`. Here we just record the hir-id of the item
// so it can fetched later.
#[derive(Copy, Clone, Encodable, Debug)]
pub struct ItemId {
Expand Down Expand Up @@ -2521,7 +2530,7 @@ pub enum ItemKind<'hir> {
/// A module.
Mod(Mod<'hir>),
/// An external module, e.g. `extern { .. }`.
ForeignMod(ForeignMod<'hir>),
ForeignMod { abi: Abi, items: &'hir [ForeignItemRef<'hir>] },
/// Module-level inline assembly (from `global_asm!`).
GlobalAsm(&'hir GlobalAsm),
/// A type alias, e.g., `type Foo = Bar<u8>`.
Expand Down Expand Up @@ -2614,6 +2623,29 @@ pub enum AssocItemKind {
Type,
}

// The bodies for items are stored "out of line", in a separate
// hashmap in the `Crate`. Here we just record the hir-id of the item
// so it can fetched later.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)]
pub struct ForeignItemId {
pub hir_id: HirId,
}

/// A reference from a foreign block to one of its items. This
/// contains the item's ID, naturally, but also the item's name and
/// some other high-level details (like whether it is an associated
/// type or method, and whether it is public). This allows other
/// passes to find the impl they want without loading the ID (which
/// means fewer edges in the incremental compilation graph).
#[derive(Debug, HashStable_Generic)]
pub struct ForeignItemRef<'hir> {
pub id: ForeignItemId,
#[stable_hasher(project(name))]
pub ident: Ident,
pub span: Span,
pub vis: Visibility<'hir>,
}

#[derive(Debug, HashStable_Generic)]
pub struct ForeignItem<'hir> {
#[stable_hasher(project(name))]
Expand Down
38 changes: 36 additions & 2 deletions compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ where
fn visit_impl_item(&mut self, impl_item: &'hir ImplItem<'hir>) {
self.visitor.visit_impl_item(impl_item);
}

fn visit_foreign_item(&mut self, foreign_item: &'hir ForeignItem<'hir>) {
self.visitor.visit_foreign_item(foreign_item);
}
}

pub trait IntoVisitor<'hir> {
Expand All @@ -88,6 +92,10 @@ where
fn visit_impl_item(&self, impl_item: &'hir ImplItem<'hir>) {
self.0.into_visitor().visit_impl_item(impl_item);
}

fn visit_foreign_item(&self, foreign_item: &'hir ForeignItem<'hir>) {
self.0.into_visitor().visit_foreign_item(foreign_item);
}
}

#[derive(Copy, Clone)]
Expand Down Expand Up @@ -128,6 +136,7 @@ pub trait Map<'hir> {
fn item(&self, id: HirId) -> &'hir Item<'hir>;
fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir>;
fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir>;
fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir>;
}

/// An erased version of `Map<'hir>`, using dynamic dispatch.
Expand All @@ -150,6 +159,9 @@ impl<'hir> Map<'hir> for ErasedMap<'hir> {
fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
self.0.impl_item(id)
}
fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
self.0.foreign_item(id)
}
}

/// Specifies what nested things a visitor wants to visit. The most
Expand Down Expand Up @@ -277,6 +289,14 @@ pub trait Visitor<'v>: Sized {
walk_list!(self, visit_impl_item, opt_item);
}

/// Like `visit_nested_item()`, but for foreign items. See
/// `visit_nested_item()` for advice on when to override this
/// method.
fn visit_nested_foreign_item(&mut self, id: ForeignItemId) {
let opt_item = self.nested_visit_map().inter().map(|map| map.foreign_item(id));
walk_list!(self, visit_foreign_item, opt_item);
}

/// Invoked to visit the body of a function, method or closure. Like
/// visit_nested_item, does nothing by default unless you override
/// `nested_visit_map` to return other than `None`, in which case it will walk
Expand Down Expand Up @@ -378,6 +398,9 @@ pub trait Visitor<'v>: Sized {
fn visit_impl_item(&mut self, ii: &'v ImplItem<'v>) {
walk_impl_item(self, ii)
}
fn visit_foreign_item_ref(&mut self, ii: &'v ForeignItemRef<'v>) {
walk_foreign_item_ref(self, ii)
}
fn visit_impl_item_ref(&mut self, ii: &'v ImplItemRef<'v>) {
walk_impl_item_ref(self, ii)
}
Expand Down Expand Up @@ -566,9 +589,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
// `visit_mod()` takes care of visiting the `Item`'s `HirId`.
visitor.visit_mod(module, item.span, item.hir_id)
}
ItemKind::ForeignMod(ref foreign_module) => {
ItemKind::ForeignMod { abi: _, items } => {
visitor.visit_id(item.hir_id);
walk_list!(visitor, visit_foreign_item, foreign_module.items);
walk_list!(visitor, visit_foreign_item_ref, items);
}
ItemKind::GlobalAsm(_) => {
visitor.visit_id(item.hir_id);
Expand Down Expand Up @@ -1012,6 +1035,17 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
}
}

pub fn walk_foreign_item_ref<'v, V: Visitor<'v>>(
visitor: &mut V,
foreign_item_ref: &'v ForeignItemRef<'v>,
) {
// N.B., deliberately force a compilation error if/when new fields are added.
let ForeignItemRef { id, ident, span: _, ref vis } = *foreign_item_ref;
visitor.visit_nested_foreign_item(id);
visitor.visit_ident(ident);
visitor.visit_vis(vis);
}

pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'v ImplItemRef<'v>) {
// N.B., deliberately force a compilation error if/when new fields are added.
let ImplItemRef { id, ident, ref kind, span: _, ref vis, ref defaultness } = *impl_item_ref;
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_hir/src/itemlikevisit.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{ImplItem, Item, TraitItem};
use super::{ForeignItem, ImplItem, Item, TraitItem};

/// The "item-like visitor" defines only the top-level methods
/// that can be invoked by `Crate::visit_all_item_likes()`. Whether
Expand Down Expand Up @@ -47,11 +47,13 @@ pub trait ItemLikeVisitor<'hir> {
fn visit_item(&mut self, item: &'hir Item<'hir>);
fn visit_trait_item(&mut self, trait_item: &'hir TraitItem<'hir>);
fn visit_impl_item(&mut self, impl_item: &'hir ImplItem<'hir>);
fn visit_foreign_item(&mut self, foreign_item: &'hir ForeignItem<'hir>);
}

/// A parallel variant of `ItemLikeVisitor`.
pub trait ParItemLikeVisitor<'hir> {
fn visit_item(&self, item: &'hir Item<'hir>);
fn visit_trait_item(&self, trait_item: &'hir TraitItem<'hir>);
fn visit_impl_item(&self, impl_item: &'hir ImplItem<'hir>);
fn visit_foreign_item(&self, foreign_item: &'hir ForeignItem<'hir>);
}
19 changes: 17 additions & 2 deletions compiler/rustc_hir/src/stable_hash_impls.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};

use crate::hir::{
BodyId, Expr, ImplItem, ImplItemId, Item, ItemId, Mod, TraitItem, TraitItemId, Ty,
VisibilityKind,
BodyId, Expr, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, Mod, TraitItem, TraitItemId,
Ty, VisibilityKind,
};
use crate::hir_id::{HirId, ItemLocalId};
use rustc_span::def_id::{DefPathHash, LocalDefId};
Expand Down Expand Up @@ -52,6 +52,15 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ImplItemId {
}
}

impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ForeignItemId {
type KeyType = (DefPathHash, ItemLocalId);

#[inline]
fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
self.hir_id.to_stable_hash_key(hcx)
}
}

impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for HirId {
fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
hcx.hash_hir_id(*self, hasher)
Expand All @@ -77,6 +86,12 @@ impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ItemId {
}
}

impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ForeignItemId {
fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
hcx.hash_reference_to_item(self.hir_id, hasher)
}
}

impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ImplItemId {
fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
hcx.hash_reference_to_item(self.hir_id, hasher)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir/src/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ impl Target {
ItemKind::Const(..) => Target::Const,
ItemKind::Fn(..) => Target::Fn,
ItemKind::Mod(..) => Target::Mod,
ItemKind::ForeignMod(..) => Target::ForeignMod,
ItemKind::ForeignMod { .. } => Target::ForeignMod,
ItemKind::GlobalAsm(..) => Target::GlobalAsm,
ItemKind::TyAlias(..) => Target::TyAlias,
ItemKind::OpaqueTy(..) => Target::OpaqueTy,
Expand Down
Loading