add a debugging mechanism to forbid edges

It is useful to track down an errant edge that is being added.  This is
not a perfect mechanism, since it doesn't consider (e.g.) if we are
in an ignored task, but it's helpful enough for now.
This commit is contained in:
Niko Matsakis 2016-08-24 07:36:54 -04:00
parent c6363b8013
commit 753590f0c5
2 changed files with 35 additions and 1 deletions

View file

@ -38,6 +38,10 @@ struct DepGraphData {
/// Work-products that we generate in this run.
work_products: RefCell<FnvHashMap<Arc<WorkProductId>, WorkProduct>>,
/// Tracks nodes that are forbidden to read/write; see
/// `DepGraph::forbid`. Used for debugging only.
forbidden: RefCell<Vec<DepNode<DefId>>>,
}
impl DepGraph {
@ -46,7 +50,8 @@ impl DepGraph {
data: Rc::new(DepGraphData {
thread: DepGraphThreadData::new(enabled),
previous_work_products: RefCell::new(FnvHashMap()),
work_products: RefCell::new(FnvHashMap())
work_products: RefCell::new(FnvHashMap()),
forbidden: RefCell::new(Vec::new()),
})
}
}
@ -70,6 +75,15 @@ impl DepGraph {
raii::DepTask::new(&self.data.thread, key)
}
/// Debugging aid -- forbid reads/writes to `key` while the return
/// value is in scope. Note that this is only available when debug
/// assertions are enabled -- you should not check in code that
/// invokes this function.
#[cfg(debug_assertions)]
pub fn forbid<'graph>(&'graph self, key: DepNode<DefId>) -> raii::Forbid<'graph> {
raii::Forbid::new(&self.data.forbidden, key)
}
pub fn with_ignore<OP,R>(&self, op: OP) -> R
where OP: FnOnce() -> R
{
@ -85,10 +99,12 @@ impl DepGraph {
}
pub fn read(&self, v: DepNode<DefId>) {
debug_assert!(!self.data.forbidden.borrow().contains(&v));
self.data.thread.enqueue(DepMessage::Read(v));
}
pub fn write(&self, v: DepNode<DefId>) {
debug_assert!(!self.data.forbidden.borrow().contains(&v));
self.data.thread.enqueue(DepMessage::Write(v));
}

View file

@ -9,6 +9,7 @@
// except according to those terms.
use hir::def_id::DefId;
use std::cell::RefCell;
use super::DepNode;
use super::thread::{DepGraphThreadData, DepMessage};
@ -47,3 +48,20 @@ impl<'graph> Drop for IgnoreTask<'graph> {
self.data.enqueue(DepMessage::PopIgnore);
}
}
pub struct Forbid<'graph> {
forbidden: &'graph RefCell<Vec<DepNode<DefId>>>
}
impl<'graph> Forbid<'graph> {
pub fn new(forbidden: &'graph RefCell<Vec<DepNode<DefId>>>, node: DepNode<DefId>) -> Self {
forbidden.borrow_mut().push(node);
Forbid { forbidden: forbidden }
}
}
impl<'graph> Drop for Forbid<'graph> {
fn drop(&mut self) {
self.forbidden.borrow_mut().pop();
}
}