From 303fdc17f6bb842668e0fdd1e1a2c16841ae7373 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 6 May 2016 05:02:05 -0400 Subject: [PATCH] cleanup dep-graph debugging code Create some re-usable filtering subroutines. --- src/librustc/dep_graph/debug.rs | 69 ++++++++++++++++++++ src/librustc/dep_graph/mod.rs | 1 + src/librustc_incremental/assert_dep_graph.rs | 28 +++----- 3 files changed, 79 insertions(+), 19 deletions(-) create mode 100644 src/librustc/dep_graph/debug.rs diff --git a/src/librustc/dep_graph/debug.rs b/src/librustc/dep_graph/debug.rs new file mode 100644 index 00000000000..15b0380374c --- /dev/null +++ b/src/librustc/dep_graph/debug.rs @@ -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 or the MIT license +// , 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(&self, node: &DepNode) -> 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> { + 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]), + }) + } + } +} diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs index 9c1bc3324db..e65f6bbcf7a 100644 --- a/src/librustc/dep_graph/mod.rs +++ b/src/librustc/dep_graph/mod.rs @@ -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; diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index e426e4d5b44..9dc50a63064 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -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 @@ impl<'a, 'tcx> dot::Labeller<'a> for GraphvizDepGraph { // 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, filter: &str) +fn node_set(query: &DepGraphQuery, filter: &DepNodeFilter) -> Option>> { 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,