separate impl-items from the impl in the HIR

This commit does not change how the incremental accounting is done, so
changes (or accessses) to an impl-item are still tagged to the enclosing
impl.

This commits adds the "main guts" of this change. It does not build on
its own.
This commit is contained in:
Niko Matsakis 2016-11-02 18:25:31 -04:00
parent 36fbf8c53c
commit b889259e2b
7 changed files with 86 additions and 11 deletions

View File

@ -45,6 +45,18 @@ pub fn visit_all_item_likes_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>
self.visitor.visit_item(i);
debug!("Ended task {:?}", task_id);
}
fn visit_impl_item(&mut self, i: &'tcx hir::ImplItem) {
// TODO -- use the def-id of the impl for now
let impl_def_id = self.tcx.map.get_parent_did(i.id);
let task_id = (self.dep_node_fn)(impl_def_id);
let _task = self.tcx.dep_graph.in_task(task_id.clone());
debug!("Started task {:?}", task_id);
assert!(!self.tcx.map.is_inlined_def_id(impl_def_id));
self.tcx.dep_graph.read(DepNode::Hir(impl_def_id));
self.visitor.visit_impl_item(i);
debug!("Ended task {:?}", task_id);
}
}
let krate = tcx.dep_graph.with_ignore(|| tcx.map.krate());

View File

@ -94,7 +94,17 @@ pub trait Visitor<'v> : Sized {
fn visit_nested_item(&mut self, id: ItemId) {
}
/// Visit the top-level item and (optionally) nested items. See
/// Invoked when a nested impl item is encountered. By default, does
/// nothing. If you want a deep walk, you need to override to
/// fetch the item contents. But most of the time, it is easier
/// (and better) to invoke `Crate::visit_all_item_likes`, which visits
/// all items in the crate in some order (but doesn't respect
/// nesting).
#[allow(unused_variables)]
fn visit_nested_impl_item(&mut self, id: ImplItemId) {
}
/// Visit the top-level item and (optionally) nested items / impl items. See
/// `visit_nested_item` for details.
fn visit_item(&mut self, i: &'v Item) {
walk_item(self, i)
@ -359,12 +369,14 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
visitor.visit_id(item.id);
visitor.visit_trait_ref(trait_ref)
}
ItemImpl(.., ref type_parameters, ref opt_trait_reference, ref typ, ref impl_items) => {
ItemImpl(.., ref type_parameters, ref opt_trait_reference, ref typ, ref impl_item_ids) => {
visitor.visit_id(item.id);
visitor.visit_generics(type_parameters);
walk_list!(visitor, visit_trait_ref, opt_trait_reference);
visitor.visit_ty(typ);
walk_list!(visitor, visit_impl_item, impl_items);
for &impl_item_id in impl_item_ids {
visitor.visit_nested_impl_item(impl_item_id);
}
}
ItemStruct(ref struct_definition, ref generics) |
ItemUnion(ref struct_definition, ref generics) => {

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use super::Item;
use super::{Item, ImplItem};
use super::intravisit::Visitor;
/// The "item-like visitor" visitor defines only the top-level methods

View File

@ -105,6 +105,7 @@ impl<'a> LoweringContext<'a> {
fn lower_crate(&mut self, c: &Crate) -> hir::Crate {
struct ItemLowerer<'lcx, 'interner: 'lcx> {
items: BTreeMap<NodeId, hir::Item>,
impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>,
lctx: &'lcx mut LoweringContext<'interner>,
}
@ -113,12 +114,20 @@ impl<'a> LoweringContext<'a> {
self.items.insert(item.id, self.lctx.lower_item(item));
visit::walk_item(self, item);
}
fn visit_impl_item(&mut self, item: &ImplItem) {
let id = self.lctx.lower_impl_item_id(item);
self.impl_items.insert(id, self.lctx.lower_impl_item(item));
visit::walk_impl_item(self, item);
}
}
let items = {
let mut item_lowerer = ItemLowerer { items: BTreeMap::new(), lctx: self };
let (items, impl_items) = {
let mut item_lowerer = ItemLowerer { items: BTreeMap::new(),
impl_items: BTreeMap::new(),
lctx: self };
visit::walk_crate(&mut item_lowerer, c);
item_lowerer.items
(item_lowerer.items, item_lowerer.impl_items)
};
hir::Crate {
@ -127,6 +136,7 @@ impl<'a> LoweringContext<'a> {
span: c.span,
exported_macros: c.exported_macros.iter().map(|m| self.lower_macro_def(m)).collect(),
items: items,
impl_items: impl_items,
}
}
@ -631,7 +641,7 @@ impl<'a> LoweringContext<'a> {
}
ItemKind::Impl(unsafety, polarity, ref generics, ref ifce, ref ty, ref impl_items) => {
let new_impl_items = impl_items.iter()
.map(|item| self.lower_impl_item(item))
.map(|item| self.lower_impl_item_id(item))
.collect();
let ifce = ifce.as_ref().map(|trait_ref| self.lower_trait_ref(trait_ref));
hir::ItemImpl(self.lower_unsafety(unsafety),
@ -707,6 +717,10 @@ impl<'a> LoweringContext<'a> {
})
}
fn lower_impl_item_id(&mut self, i: &ImplItem) -> hir::ImplItemId {
hir::ImplItemId { id: i.id }
}
fn lower_mod(&mut self, m: &Mod) -> hir::Mod {
hir::Mod {
inner: m.inner,

View File

@ -378,6 +378,15 @@ impl<'ast> Map<'ast> {
self.forest.krate()
}
pub fn impl_item(&self, id: ImplItemId) -> &'ast ImplItem {
// TODO right now this triggers a read of the whole impl
self.read(id.id);
// NB: intentionally bypass `self.forest.krate()` so that we
// do not trigger a read of the whole krate here
self.forest.krate.impl_item(id)
}
/// Get the attributes on the krate. This is preferable to
/// invoking `krate.attrs` because it registers a tighter
/// dep-graph access.

View File

@ -424,6 +424,8 @@ pub struct Crate {
// detected, which in turn can make compile-fail tests yield
// slightly different results.
pub items: BTreeMap<NodeId, Item>,
pub impl_items: BTreeMap<ImplItemId, ImplItem>,
}
impl Crate {
@ -431,6 +433,10 @@ impl Crate {
&self.items[&id]
}
pub fn impl_item(&self, id: ImplItemId) -> &ImplItem {
&self.impl_items[&id]
}
/// Visits all items in the crate in some determinstic (but
/// unspecified) order. If you just need to process every item,
/// but don't care about nesting, this method is the best choice.
@ -445,6 +451,10 @@ impl Crate {
for (_, item) in &self.items {
visitor.visit_item(item);
}
for (_, impl_item) in &self.impl_items {
visitor.visit_impl_item(impl_item);
}
}
}
@ -1042,6 +1052,14 @@ pub enum TraitItem_ {
TypeTraitItem(TyParamBounds, Option<P<Ty>>),
}
// 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
// so it can fetched later.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct ImplItemId {
pub id: NodeId,
}
/// Represents anything within an `impl` block
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct ImplItem {
@ -1528,7 +1546,7 @@ pub enum Item_ {
Generics,
Option<TraitRef>, // (optional) trait this impl implements
P<Ty>, // self
HirVec<ImplItem>),
HirVec<ImplItemId>),
}
impl Item_ {

View File

@ -808,8 +808,8 @@ impl<'a> State<'a> {
space(&mut self.s)?;
self.bopen()?;
self.print_inner_attributes(&item.attrs)?;
for impl_item in impl_items {
self.print_impl_item(impl_item)?;
for &impl_item in impl_items {
self.print_impl_item_id(impl_item)?;
}
self.bclose(item.span)?;
}
@ -1020,6 +1020,16 @@ impl<'a> State<'a> {
self.ann.post(self, NodeSubItem(ti.id))
}
pub fn print_impl_item_id(&mut self, item_id: hir::ImplItemId) -> io::Result<()> {
if let Some(krate) = self.krate {
// skip nested items if krate context was not provided
let item = &krate.impl_item(item_id);
self.print_impl_item(item)
} else {
Ok(())
}
}
pub fn print_impl_item(&mut self, ii: &hir::ImplItem) -> io::Result<()> {
self.ann.pre(self, NodeSubItem(ii.id))?;
self.hardbreak_if_not_bol()?;