Give function bodies their own dep graph node
This commit is contained in:
parent
16eedd2a78
commit
936dbbce37
@ -42,6 +42,9 @@ pub enum DepNode<D: Clone + Debug> {
|
||||
// Represents the HIR node with the given node-id
|
||||
Hir(D),
|
||||
|
||||
// Represents the body of a function or method
|
||||
HirBody(D),
|
||||
|
||||
// Represents the metadata for a given HIR node, typically found
|
||||
// in an extern crate.
|
||||
MetaData(D),
|
||||
@ -150,6 +153,7 @@ impl<D: Clone + Debug> DepNode<D> {
|
||||
CollectItem,
|
||||
BorrowCheck,
|
||||
Hir,
|
||||
HirBody,
|
||||
TransCrateItem,
|
||||
TypeckItemType,
|
||||
TypeckItemBody,
|
||||
@ -199,6 +203,7 @@ impl<D: Clone + Debug> DepNode<D> {
|
||||
WorkProduct(ref id) => Some(WorkProduct(id.clone())),
|
||||
|
||||
Hir(ref d) => op(d).map(Hir),
|
||||
HirBody(ref d) => op(d).map(HirBody),
|
||||
MetaData(ref d) => op(d).map(MetaData),
|
||||
CollectItem(ref d) => op(d).map(CollectItem),
|
||||
CoherenceCheckImpl(ref d) => op(d).map(CoherenceCheckImpl),
|
||||
|
@ -256,18 +256,39 @@ impl<'ast> Map<'ast> {
|
||||
let map = self.map.borrow();
|
||||
let mut id = id0;
|
||||
if !self.is_inlined_node_id(id) {
|
||||
let mut last_expr = None;
|
||||
loop {
|
||||
match map[id.as_usize()] {
|
||||
EntryItem(_, item) => {
|
||||
assert_eq!(id, item.id);
|
||||
let def_id = self.local_def_id(id);
|
||||
assert!(!self.is_inlined_def_id(def_id));
|
||||
|
||||
if let Some(last_id) = last_expr {
|
||||
// The body of the item may have a separate dep node
|
||||
// (Note that impl/trait items don't currently have
|
||||
// their own dep node, so there's also just one
|
||||
// HirBody node for all the items)
|
||||
if self.is_body(last_id, item) {
|
||||
return DepNode::HirBody(def_id);
|
||||
}
|
||||
}
|
||||
return DepNode::Hir(def_id);
|
||||
}
|
||||
|
||||
EntryImplItem(..) => {
|
||||
EntryImplItem(_, item) => {
|
||||
let def_id = self.local_def_id(id);
|
||||
assert!(!self.is_inlined_def_id(def_id));
|
||||
|
||||
if let Some(last_id) = last_expr {
|
||||
// The body of the item may have a separate dep node
|
||||
// (Note that impl/trait items don't currently have
|
||||
// their own dep node, so there's also just one
|
||||
// HirBody node for all the items)
|
||||
if self.is_impl_item_body(last_id, item) {
|
||||
return DepNode::HirBody(def_id);
|
||||
}
|
||||
}
|
||||
return DepNode::Hir(def_id);
|
||||
}
|
||||
|
||||
@ -275,7 +296,6 @@ impl<'ast> Map<'ast> {
|
||||
EntryTraitItem(p, _) |
|
||||
EntryVariant(p, _) |
|
||||
EntryField(p, _) |
|
||||
EntryExpr(p, _) |
|
||||
EntryStmt(p, _) |
|
||||
EntryTy(p, _) |
|
||||
EntryTraitRef(p, _) |
|
||||
@ -288,6 +308,11 @@ impl<'ast> Map<'ast> {
|
||||
EntryVisibility(p, _) =>
|
||||
id = p,
|
||||
|
||||
EntryExpr(p, _) => {
|
||||
last_expr = Some(id);
|
||||
id = p;
|
||||
}
|
||||
|
||||
RootCrate =>
|
||||
return DepNode::Krate,
|
||||
|
||||
@ -345,6 +370,29 @@ impl<'ast> Map<'ast> {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_body(&self, node_id: NodeId, item: &Item) -> bool {
|
||||
match item.node {
|
||||
ItemFn(_, _, _, _, _, body) => body.node_id() == node_id,
|
||||
// Since trait/impl items currently don't get their own dep nodes,
|
||||
// we check here whether node_id is the body of any of the items.
|
||||
// Once they get their own dep nodes, this can go away
|
||||
ItemTrait(_, _, _, ref trait_items) => {
|
||||
trait_items.iter().any(|trait_item| { match trait_item.node {
|
||||
MethodTraitItem(_, Some(body)) => body.node_id() == node_id,
|
||||
_ => false
|
||||
}})
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
fn is_impl_item_body(&self, node_id: NodeId, item: &ImplItem) -> bool {
|
||||
match item.node {
|
||||
ImplItemKind::Method(_, body) => body.node_id() == node_id,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn num_local_def_ids(&self) -> usize {
|
||||
self.definitions.borrow().len()
|
||||
}
|
||||
|
@ -33,7 +33,6 @@ use graphviz::IntoCow;
|
||||
use syntax::ast;
|
||||
use rustc::hir::{Expr, PatKind};
|
||||
use rustc::hir;
|
||||
use rustc::hir::intravisit::FnKind;
|
||||
use syntax::ptr::P;
|
||||
use syntax::codemap;
|
||||
use syntax::attr::IntType;
|
||||
|
@ -149,19 +149,27 @@ impl<'a, 'tcx> HashItemsVisitor<'a, 'tcx> {
|
||||
{
|
||||
assert!(def_id.is_local());
|
||||
debug!("HashItemsVisitor::calculate(def_id={:?})", def_id);
|
||||
self.calculate_def_hash(DepNode::Hir(def_id), false, &mut walk_op);
|
||||
self.calculate_def_hash(DepNode::HirBody(def_id), true, &mut walk_op);
|
||||
}
|
||||
|
||||
fn calculate_def_hash<W>(&mut self, dep_node: DepNode<DefId>, hash_bodies: bool, walk_op: &mut W)
|
||||
where W: for<'v> FnMut(&mut StrictVersionHashVisitor<'v, 'a, 'tcx>)
|
||||
{
|
||||
let mut state = IchHasher::new();
|
||||
walk_op(&mut StrictVersionHashVisitor::new(&mut state,
|
||||
self.tcx,
|
||||
&mut self.def_path_hashes,
|
||||
&mut self.codemap,
|
||||
self.hash_spans));
|
||||
self.hash_spans,
|
||||
hash_bodies));
|
||||
let bytes_hashed = state.bytes_hashed();
|
||||
let item_hash = state.finish();
|
||||
self.hashes.insert(DepNode::Hir(def_id), item_hash);
|
||||
debug!("calculate_item_hash: def_id={:?} hash={:?}", def_id, item_hash);
|
||||
debug!("calculate_def_hash: dep_node={:?} hash={:?}", dep_node, item_hash);
|
||||
self.hashes.insert(dep_node, item_hash);
|
||||
|
||||
let bytes_hashed = self.tcx.sess.perf_stats.incr_comp_bytes_hashed.get() +
|
||||
bytes_hashed;
|
||||
bytes_hashed;
|
||||
self.tcx.sess.perf_stats.incr_comp_bytes_hashed.set(bytes_hashed);
|
||||
}
|
||||
|
||||
@ -200,7 +208,8 @@ impl<'a, 'tcx> HashItemsVisitor<'a, 'tcx> {
|
||||
self.tcx,
|
||||
&mut self.def_path_hashes,
|
||||
&mut self.codemap,
|
||||
self.hash_spans);
|
||||
self.hash_spans,
|
||||
false);
|
||||
visitor.hash_attributes(&krate.attrs);
|
||||
}
|
||||
|
||||
|
@ -52,6 +52,7 @@ pub struct StrictVersionHashVisitor<'a, 'hash: 'a, 'tcx: 'hash> {
|
||||
hash_spans: bool,
|
||||
codemap: &'a mut CachingCodemapView<'tcx>,
|
||||
overflow_checks_enabled: bool,
|
||||
hash_bodies: bool,
|
||||
}
|
||||
|
||||
impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> {
|
||||
@ -59,7 +60,8 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> {
|
||||
tcx: TyCtxt<'hash, 'tcx, 'tcx>,
|
||||
def_path_hashes: &'a mut DefPathHashes<'hash, 'tcx>,
|
||||
codemap: &'a mut CachingCodemapView<'tcx>,
|
||||
hash_spans: bool)
|
||||
hash_spans: bool,
|
||||
hash_bodies: bool)
|
||||
-> Self {
|
||||
let check_overflow = tcx.sess.opts.debugging_opts.force_overflow_checks
|
||||
.unwrap_or(tcx.sess.opts.debug_assertions);
|
||||
@ -71,6 +73,7 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> {
|
||||
hash_spans: hash_spans,
|
||||
codemap: codemap,
|
||||
overflow_checks_enabled: check_overflow,
|
||||
hash_bodies: hash_bodies,
|
||||
}
|
||||
}
|
||||
|
||||
@ -459,15 +462,16 @@ fn saw_ty(node: &Ty_) -> SawTyComponent {
|
||||
#[derive(Hash)]
|
||||
enum SawTraitOrImplItemComponent {
|
||||
SawTraitOrImplItemConst,
|
||||
SawTraitOrImplItemMethod(Unsafety, Constness, Abi),
|
||||
// The boolean signifies whether a body is present
|
||||
SawTraitOrImplItemMethod(Unsafety, Constness, Abi, bool),
|
||||
SawTraitOrImplItemType
|
||||
}
|
||||
|
||||
fn saw_trait_item(ti: &TraitItem_) -> SawTraitOrImplItemComponent {
|
||||
match *ti {
|
||||
ConstTraitItem(..) => SawTraitOrImplItemConst,
|
||||
MethodTraitItem(ref sig, _) =>
|
||||
SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi),
|
||||
MethodTraitItem(ref sig, ref body) =>
|
||||
SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi, body.is_some()),
|
||||
TypeTraitItem(..) => SawTraitOrImplItemType
|
||||
}
|
||||
}
|
||||
@ -476,7 +480,7 @@ fn saw_impl_item(ii: &ImplItemKind) -> SawTraitOrImplItemComponent {
|
||||
match *ii {
|
||||
ImplItemKind::Const(..) => SawTraitOrImplItemConst,
|
||||
ImplItemKind::Method(ref sig, _) =>
|
||||
SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi),
|
||||
SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi, true),
|
||||
ImplItemKind::Type(..) => SawTraitOrImplItemType
|
||||
}
|
||||
}
|
||||
@ -509,6 +513,14 @@ macro_rules! hash_span {
|
||||
}
|
||||
|
||||
impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'hash, 'tcx> {
|
||||
fn nested_visit_map(&mut self) -> Option<(&hir::map::Map<'tcx>, visit::NestedVisitMode)> {
|
||||
if self.hash_bodies {
|
||||
Some((&self.tcx.map, visit::NestedVisitMode::OnlyBodies))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_variant_data(&mut self,
|
||||
s: &'tcx VariantData,
|
||||
name: Name,
|
||||
@ -609,7 +621,8 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has
|
||||
|
||||
fn visit_mod(&mut self, m: &'tcx Mod, _s: Span, n: NodeId) {
|
||||
debug!("visit_mod: st={:?}", self.st);
|
||||
SawMod.hash(self.st); visit::walk_mod(self, m, n)
|
||||
SawMod.hash(self.st);
|
||||
visit::walk_mod(self, m, n)
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: &'tcx Ty) {
|
||||
|
@ -114,7 +114,8 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
|
||||
|
||||
match dep_node {
|
||||
DepNode::Krate |
|
||||
DepNode::Hir(_) => {
|
||||
DepNode::Hir(_) |
|
||||
DepNode::HirBody(_) => {
|
||||
// HIR nodes are inputs, so if we are asserting that the HIR node is
|
||||
// dirty, we check the dirty input set.
|
||||
if !self.dirty_inputs.contains(&dep_node) {
|
||||
@ -143,7 +144,8 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
|
||||
|
||||
match dep_node {
|
||||
DepNode::Krate |
|
||||
DepNode::Hir(_) => {
|
||||
DepNode::Hir(_) |
|
||||
DepNode::HirBody(_) => {
|
||||
// For HIR nodes, check the inputs.
|
||||
if self.dirty_inputs.contains(&dep_node) {
|
||||
let dep_node_str = self.dep_node_str(&dep_node);
|
||||
|
@ -45,7 +45,9 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> {
|
||||
pub fn is_hashable(dep_node: &DepNode<DefId>) -> bool {
|
||||
match *dep_node {
|
||||
DepNode::Krate |
|
||||
DepNode::Hir(_) => true,
|
||||
DepNode::Hir(_) |
|
||||
DepNode::HirBody(_) =>
|
||||
true,
|
||||
DepNode::MetaData(def_id) => !def_id.is_local(),
|
||||
_ => false,
|
||||
}
|
||||
@ -58,7 +60,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> {
|
||||
}
|
||||
|
||||
// HIR nodes (which always come from our crate) are an input:
|
||||
DepNode::Hir(def_id) => {
|
||||
DepNode::Hir(def_id) | DepNode::HirBody(def_id) => {
|
||||
assert!(def_id.is_local(),
|
||||
"cannot hash HIR for non-local def-id {:?} => {:?}",
|
||||
def_id,
|
||||
|
@ -145,8 +145,8 @@ pub fn encode_dep_graph(preds: &Predecessors,
|
||||
for (&target, sources) in &preds.inputs {
|
||||
match *target {
|
||||
DepNode::MetaData(ref def_id) => {
|
||||
// Metadata *targets* are always local metadata nodes. We handle
|
||||
// those in `encode_metadata_hashes`, which comes later.
|
||||
// Metadata *targets* are always local metadata nodes. We have
|
||||
// already handled those in `encode_metadata_hashes`.
|
||||
assert!(def_id.is_local());
|
||||
continue;
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ mod x {
|
||||
mod y {
|
||||
use x;
|
||||
|
||||
#[rustc_dirty(label="TypeckItemBody", cfg="rpass2")]
|
||||
#[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
|
||||
pub fn y() {
|
||||
x::x();
|
||||
}
|
||||
|
@ -46,12 +46,14 @@ mod mod3 {
|
||||
mod mod3 {
|
||||
use Trait2;
|
||||
|
||||
#[rustc_dirty(label="Hir", cfg="rpass2")]
|
||||
#[rustc_clean(label="Hir", cfg="rpass2")]
|
||||
#[rustc_dirty(label="HirBody", cfg="rpass2")]
|
||||
fn bar() {
|
||||
().method();
|
||||
}
|
||||
|
||||
#[rustc_clean(label="Hir", cfg="rpass2")]
|
||||
#[rustc_clean(label="HirBody", cfg="rpass2")]
|
||||
fn baz() {
|
||||
22; // no method call, traits in scope don't matter
|
||||
}
|
||||
|
@ -23,11 +23,14 @@ fn foo() {
|
||||
|
||||
#[cfg(rpass2)]
|
||||
#[rustc_clean(label="Hir", cfg="rpass2")]
|
||||
#[rustc_clean(label="HirBody", cfg="rpass2")]
|
||||
fn foo() {
|
||||
#[rustc_clean(label="Hir", cfg="rpass2")]
|
||||
#[rustc_clean(label="HirBody", cfg="rpass2")]
|
||||
fn baz() { } // order is different...
|
||||
|
||||
#[rustc_clean(label="Hir", cfg="rpass2")]
|
||||
#[rustc_clean(label="HirBody", cfg="rpass2")]
|
||||
fn bar() { } // but that doesn't matter.
|
||||
|
||||
fn bap() { } // neither does adding a new item
|
||||
|
@ -45,11 +45,13 @@ mod mod3 {
|
||||
use test;
|
||||
|
||||
#[rustc_clean(label="Hir", cfg="rpass2")]
|
||||
#[rustc_clean(label="HirBody", cfg="rpass2")]
|
||||
fn in_expr() {
|
||||
Foo(0);
|
||||
}
|
||||
|
||||
#[rustc_clean(label="Hir", cfg="rpass2")]
|
||||
#[rustc_clean(label="HirBody", cfg="rpass2")]
|
||||
fn in_type() {
|
||||
test::<Foo>();
|
||||
}
|
||||
@ -60,12 +62,14 @@ mod mod3 {
|
||||
use test;
|
||||
use mod2::Foo; // <-- This changed!
|
||||
|
||||
#[rustc_dirty(label="Hir", cfg="rpass3")]
|
||||
#[rustc_clean(label="Hir", cfg="rpass3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="rpass3")]
|
||||
fn in_expr() {
|
||||
Foo(0);
|
||||
}
|
||||
|
||||
#[rustc_dirty(label="Hir", cfg="rpass3")]
|
||||
#[rustc_clean(label="Hir", cfg="rpass3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="rpass3")]
|
||||
fn in_type() {
|
||||
test::<Foo>();
|
||||
}
|
||||
|
@ -17,17 +17,17 @@
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
#[rustc_clean(label="Hir", cfg="rpass2")]
|
||||
#[rustc_clean(label="HirBody", cfg="rpass2")]
|
||||
fn line_same() {
|
||||
let _ = line!();
|
||||
}
|
||||
|
||||
#[rustc_clean(label="Hir", cfg="rpass2")]
|
||||
#[rustc_clean(label="HirBody", cfg="rpass2")]
|
||||
fn col_same() {
|
||||
let _ = column!();
|
||||
}
|
||||
|
||||
#[rustc_clean(label="Hir", cfg="rpass2")]
|
||||
#[rustc_clean(label="HirBody", cfg="rpass2")]
|
||||
fn file_same() {
|
||||
let _ = file!();
|
||||
}
|
||||
@ -38,7 +38,7 @@ fn line_different() {
|
||||
}
|
||||
|
||||
#[cfg(rpass2)]
|
||||
#[rustc_dirty(label="Hir", cfg="rpass2")]
|
||||
#[rustc_dirty(label="HirBody", cfg="rpass2")]
|
||||
fn line_different() {
|
||||
let _ = line!();
|
||||
}
|
||||
@ -49,7 +49,7 @@ fn col_different() {
|
||||
}
|
||||
|
||||
#[cfg(rpass2)]
|
||||
#[rustc_dirty(label="Hir", cfg="rpass2")]
|
||||
#[rustc_dirty(label="HirBody", cfg="rpass2")]
|
||||
fn col_different() {
|
||||
let _ = column!();
|
||||
}
|
||||
|
@ -22,4 +22,5 @@ pub fn main() {}
|
||||
|
||||
#[cfg(rpass2)]
|
||||
#[rustc_clean(label="Hir", cfg="rpass2")]
|
||||
#[rustc_clean(label="HirBody", cfg="rpass2")]
|
||||
pub fn main() {}
|
||||
|
@ -22,4 +22,5 @@ pub fn main() {}
|
||||
|
||||
#[cfg(rpass2)]
|
||||
#[rustc_dirty(label="Hir", cfg="rpass2")]
|
||||
#[rustc_dirty(label="HirBody", cfg="rpass2")]
|
||||
pub fn main() {}
|
||||
|
Loading…
Reference in New Issue
Block a user