]> git.lizzy.rs Git - rust.git/commitdiff
cleanup dep-graph debugging code
authorNiko Matsakis <niko@alum.mit.edu>
Fri, 6 May 2016 09:02:05 +0000 (05:02 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Wed, 18 May 2016 14:11:36 +0000 (10:11 -0400)
Create some re-usable filtering subroutines.

src/librustc/dep_graph/debug.rs [new file with mode: 0644]
src/librustc/dep_graph/mod.rs
src/librustc_incremental/assert_dep_graph.rs

diff --git a/src/librustc/dep_graph/debug.rs b/src/librustc/dep_graph/debug.rs
new file mode 100644 (file)
index 0000000..15b0380
--- /dev/null
@@ -0,0 +1,69 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Code for debugging the dep-graph.
+
+use super::dep_node::DepNode;
+use std::error::Error;
+use std::fmt::Debug;
+
+/// A dep-node filter goes from a user-defined string to a query over
+/// nodes. Right now the format is like this:
+///
+///     x & y & z
+///
+/// where the format-string of the dep-node must contain `x`, `y`, and
+/// `z`.
+#[derive(Debug)]
+pub struct DepNodeFilter {
+    text: String
+}
+
+impl DepNodeFilter {
+    pub fn new(text: &str) -> Self {
+        DepNodeFilter {
+            text: text.trim().to_string()
+        }
+    }
+
+    /// True if all nodes always pass the filter.
+    pub fn accepts_all(&self) -> bool {
+        self.text.is_empty()
+    }
+
+    /// Tests whether `node` meets the filter, returning true if so.
+    pub fn test<D: Clone + Debug>(&self, node: &DepNode<D>) -> bool {
+        let debug_str = format!("{:?}", node);
+        self.text.split("&")
+                 .map(|s| s.trim())
+                 .all(|f| debug_str.contains(f))
+    }
+}
+
+/// A filter like `F -> G` where `F` and `G` are valid dep-node
+/// filters. This can be used to test the source/target independently.
+pub struct EdgeFilter {
+    pub source: DepNodeFilter,
+    pub target: DepNodeFilter,
+}
+
+impl EdgeFilter {
+    pub fn new(test: &str) -> Result<EdgeFilter, Box<Error>> {
+        let parts: Vec<_> = test.split("->").collect();
+        if parts.len() != 2 {
+            Err(format!("expected a filter like `a&b -> c&d`, not `{}`", test).into())
+        } else {
+            Ok(EdgeFilter {
+                source: DepNodeFilter::new(parts[0]),
+                target: DepNodeFilter::new(parts[1]),
+            })
+        }
+    }
+}
index 9c1bc3324dbbf2d21ce1583e4bf6ebd7f6f87f33..e65f6bbcf7aab672acdf3028b794582cf6180450 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+pub mod debug;
 mod dep_node;
 mod dep_tracking_map;
 mod edges;
index e426e4d5b44af40d4a429e4f6ddf92397ce515ca..9dc50a6306406d8684afcab039c98331e75f4417 100644 (file)
@@ -44,6 +44,7 @@
 
 use graphviz as dot;
 use rustc::dep_graph::{DepGraphQuery, DepNode};
+use rustc::dep_graph::debug::{DepNodeFilter, EdgeFilter};
 use rustc::hir::def_id::DefId;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fnv::{FnvHashMap, FnvHashSet};
@@ -220,12 +221,11 @@ fn dump_graph(tcx: TyCtxt) {
     let nodes = match env::var("RUST_DEP_GRAPH_FILTER") {
         Ok(string) => {
             // Expect one of: "-> target", "source -> target", or "source ->".
-            let parts: Vec<_> = string.split("->").collect();
-            if parts.len() > 2 {
-                bug!("Invalid RUST_DEP_GRAPH_FILTER: expected '[source] -> [target]'");
-            }
-            let sources = node_set(&query, &parts[0]);
-            let targets = node_set(&query, &parts[1]);
+            let edge_filter = EdgeFilter::new(&string).unwrap_or_else(|e| {
+                bug!("invalid filter: {}", e)
+            });
+            let sources = node_set(&query, &edge_filter.source);
+            let targets = node_set(&query, &edge_filter.target);
             filter_nodes(&query, &sources, &targets)
         }
         Err(_) => {
@@ -295,26 +295,16 @@ fn node_label(&self, n: &DepNode<DefId>) -> dot::LabelText {
 // Given an optional filter like `"x,y,z"`, returns either `None` (no
 // filter) or the set of nodes whose labels contain all of those
 // substrings.
-fn node_set(query: &DepGraphQuery<DefId>, filter: &str)
+fn node_set(query: &DepGraphQuery<DefId>, filter: &DepNodeFilter)
             -> Option<FnvHashSet<DepNode<DefId>>>
 {
     debug!("node_set(filter={:?})", filter);
 
-    if filter.trim().is_empty() {
+    if filter.accepts_all() {
         return None;
     }
 
-    let filters: Vec<&str> = filter.split("&").map(|s| s.trim()).collect();
-
-    debug!("node_set: filters={:?}", filters);
-
-    Some(query.nodes()
-         .into_iter()
-         .filter(|n| {
-             let s = format!("{:?}", n);
-             filters.iter().all(|f| s.contains(f))
-         })
-        .collect())
+    Some(query.nodes().into_iter().filter(|n| filter.test(n)).collect())
 }
 
 fn filter_nodes(query: &DepGraphQuery<DefId>,