From 753590f0c52c0ca54e7b80c1cc90f72bb8bbc8fb Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 24 Aug 2016 07:36:54 -0400 Subject: [PATCH] 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. --- src/librustc/dep_graph/graph.rs | 18 +++++++++++++++++- src/librustc/dep_graph/raii.rs | 18 ++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index bb027b11b45a..ca441c4bc3ff 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -38,6 +38,10 @@ struct DepGraphData { /// Work-products that we generate in this run. work_products: RefCell, WorkProduct>>, + + /// Tracks nodes that are forbidden to read/write; see + /// `DepGraph::forbid`. Used for debugging only. + forbidden: RefCell>>, } 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) -> raii::Forbid<'graph> { + raii::Forbid::new(&self.data.forbidden, key) + } + pub fn with_ignore(&self, op: OP) -> R where OP: FnOnce() -> R { @@ -85,10 +99,12 @@ impl DepGraph { } pub fn read(&self, v: DepNode) { + debug_assert!(!self.data.forbidden.borrow().contains(&v)); self.data.thread.enqueue(DepMessage::Read(v)); } pub fn write(&self, v: DepNode) { + debug_assert!(!self.data.forbidden.borrow().contains(&v)); self.data.thread.enqueue(DepMessage::Write(v)); } diff --git a/src/librustc/dep_graph/raii.rs b/src/librustc/dep_graph/raii.rs index c43d493d1767..b344eb486240 100644 --- a/src/librustc/dep_graph/raii.rs +++ b/src/librustc/dep_graph/raii.rs @@ -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>> +} + +impl<'graph> Forbid<'graph> { + pub fn new(forbidden: &'graph RefCell>>, node: DepNode) -> Self { + forbidden.borrow_mut().push(node); + Forbid { forbidden: forbidden } + } +} + +impl<'graph> Drop for Forbid<'graph> { + fn drop(&mut self) { + self.forbidden.borrow_mut().pop(); + } +}