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:
parent
36fbf8c53c
commit
b889259e2b
@ -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());
|
||||
|
@ -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) => {
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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_ {
|
||||
|
@ -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()?;
|
||||
|
Loading…
x
Reference in New Issue
Block a user