diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 84c84a7ed57a..73b96651b05e 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -10,7 +10,16 @@ use std::fmt::Debug; -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] +macro_rules! try_opt { + ($e:expr) => ( + match $e { + Some(r) => r, + None => return None, + } + ) +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum DepNode { // The `D` type is "how definitions are identified". // During compilation, it is always `DefId`, but when serializing @@ -116,7 +125,7 @@ pub enum DepNode { // which would yield an overly conservative dep-graph. TraitItems(D), ReprHints(D), - TraitSelect(D), + TraitSelect(D, Vec), } impl DepNode { @@ -212,7 +221,11 @@ impl DepNode { TraitImpls(ref d) => op(d).map(TraitImpls), TraitItems(ref d) => op(d).map(TraitItems), ReprHints(ref d) => op(d).map(ReprHints), - TraitSelect(ref d) => op(d).map(TraitSelect), + TraitSelect(ref d, ref type_ds) => { + let d = try_opt!(op(d)); + let type_ds = try_opt!(type_ds.iter().map(|d| op(d)).collect()); + Some(TraitSelect(d, type_ds)) + } } } } diff --git a/src/librustc/dep_graph/query.rs b/src/librustc/dep_graph/query.rs index 93248edb197c..7a780c1d4ae2 100644 --- a/src/librustc/dep_graph/query.rs +++ b/src/librustc/dep_graph/query.rs @@ -47,26 +47,26 @@ impl DepGraphQuery { self.indices.contains_key(&node) } - pub fn nodes(&self) -> Vec> { + pub fn nodes(&self) -> Vec<&DepNode> { self.graph.all_nodes() .iter() - .map(|n| n.data.clone()) + .map(|n| &n.data) .collect() } - pub fn edges(&self) -> Vec<(DepNode,DepNode)> { + pub fn edges(&self) -> Vec<(&DepNode,&DepNode)> { self.graph.all_edges() .iter() .map(|edge| (edge.source(), edge.target())) - .map(|(s, t)| (self.graph.node_data(s).clone(), - self.graph.node_data(t).clone())) + .map(|(s, t)| (self.graph.node_data(s), + self.graph.node_data(t))) .collect() } - fn reachable_nodes(&self, node: DepNode, direction: Direction) -> Vec> { - if let Some(&index) = self.indices.get(&node) { + fn reachable_nodes(&self, node: &DepNode, direction: Direction) -> Vec<&DepNode> { + if let Some(&index) = self.indices.get(node) { self.graph.depth_traverse(index, direction) - .map(|s| self.graph.node_data(s).clone()) + .map(|s| self.graph.node_data(s)) .collect() } else { vec![] @@ -75,20 +75,20 @@ impl DepGraphQuery { /// All nodes reachable from `node`. In other words, things that /// will have to be recomputed if `node` changes. - pub fn transitive_successors(&self, node: DepNode) -> Vec> { + pub fn transitive_successors(&self, node: &DepNode) -> Vec<&DepNode> { self.reachable_nodes(node, OUTGOING) } /// All nodes that can reach `node`. - pub fn transitive_predecessors(&self, node: DepNode) -> Vec> { + pub fn transitive_predecessors(&self, node: &DepNode) -> Vec<&DepNode> { self.reachable_nodes(node, INCOMING) } /// Just the outgoing edges from `node`. - pub fn immediate_successors(&self, node: DepNode) -> Vec> { + pub fn immediate_successors(&self, node: &DepNode) -> Vec<&DepNode> { if let Some(&index) = self.indices.get(&node) { self.graph.successor_nodes(index) - .map(|s| self.graph.node_data(s).clone()) + .map(|s| self.graph.node_data(s)) .collect() } else { vec![] diff --git a/src/librustc/dep_graph/raii.rs b/src/librustc/dep_graph/raii.rs index 13151d169fc3..92cecabaa182 100644 --- a/src/librustc/dep_graph/raii.rs +++ b/src/librustc/dep_graph/raii.rs @@ -20,14 +20,14 @@ pub struct DepTask<'graph> { impl<'graph> DepTask<'graph> { pub fn new(data: &'graph DepGraphThreadData, key: DepNode) -> DepTask<'graph> { - data.enqueue(DepMessage::PushTask(key)); + data.enqueue(DepMessage::PushTask(key.clone())); DepTask { data: data, key: key } } } impl<'graph> Drop for DepTask<'graph> { fn drop(&mut self) { - self.data.enqueue(DepMessage::PopTask(self.key)); + self.data.enqueue(DepMessage::PopTask(self.key.clone())); } } diff --git a/src/librustc/dep_graph/visit.rs b/src/librustc/dep_graph/visit.rs index 9133b4d22eeb..5dd71db2f183 100644 --- a/src/librustc/dep_graph/visit.rs +++ b/src/librustc/dep_graph/visit.rs @@ -39,7 +39,7 @@ pub fn visit_all_items_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn visit_item(&mut self, i: &'tcx hir::Item) { let item_def_id = self.tcx.map.local_def_id(i.id); let task_id = (self.dep_node_fn)(item_def_id); - let _task = self.tcx.dep_graph.in_task(task_id); + let _task = self.tcx.dep_graph.in_task(task_id.clone()); debug!("Started task {:?}", task_id); self.tcx.dep_graph.read(DepNode::Hir(item_def_id)); self.visitor.visit_item(i); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 24f0671ce618..423d57cfb328 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -946,7 +946,7 @@ impl<'tcx> TraitPredicate<'tcx> { /// Creates the dep-node for selecting/evaluating this trait reference. fn dep_node(&self) -> DepNode { - DepNode::TraitSelect(self.def_id()) + DepNode::TraitSelect(self.def_id(), vec![]) } pub fn input_types(&self) -> &[Ty<'tcx>] { @@ -1768,9 +1768,8 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> { stack: &mut Vec>) { - let dep_node = DepNode::SizedConstraint(self.did); - - if self.sized_constraint.get(dep_node).is_some() { + let dep_node = || DepNode::SizedConstraint(self.did); + if self.sized_constraint.get(dep_node()).is_some() { return; } @@ -1780,7 +1779,7 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> { // // Consider the type as Sized in the meanwhile to avoid // further errors. - self.sized_constraint.fulfill(dep_node, tcx.types.err); + self.sized_constraint.fulfill(dep_node(), tcx.types.err); return; } @@ -1803,14 +1802,14 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> { _ => tcx.mk_tup(tys) }; - match self.sized_constraint.get(dep_node) { + match self.sized_constraint.get(dep_node()) { Some(old_ty) => { debug!("calculate_sized_constraint: {:?} recurred", self); assert_eq!(old_ty, tcx.types.err) } None => { debug!("calculate_sized_constraint: {:?} => {:?}", self, ty); - self.sized_constraint.fulfill(dep_node, ty) + self.sized_constraint.fulfill(dep_node(), ty) } } } diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index 9dc50a630640..1c0274cdcca9 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -195,7 +195,7 @@ fn check_paths<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } }; - for &(_, source_def_id, source_dep_node) in sources { + for &(_, source_def_id, ref source_dep_node) in sources { let dependents = query.transitive_successors(source_dep_node); for &(target_span, ref target_pass, _, ref target_dep_node) in targets { if !dependents.contains(&target_dep_node) { @@ -239,7 +239,7 @@ fn dump_graph(tcx: TyCtxt) { { // dump a .txt file with just the edges: let txt_path = format!("{}.txt", path); let mut file = File::create(&txt_path).unwrap(); - for &(source, target) in &edges { + for &(ref source, ref target) in &edges { write!(file, "{:?} -> {:?}\n", source, target).unwrap(); } } @@ -252,34 +252,34 @@ fn dump_graph(tcx: TyCtxt) { } } -pub struct GraphvizDepGraph(FnvHashSet>, - Vec<(DepNode, DepNode)>); +pub struct GraphvizDepGraph<'q>(FnvHashSet<&'q DepNode>, + Vec<(&'q DepNode, &'q DepNode)>); -impl<'a, 'tcx> dot::GraphWalk<'a> for GraphvizDepGraph { - type Node = DepNode; - type Edge = (DepNode, DepNode); - fn nodes(&self) -> dot::Nodes> { +impl<'a, 'tcx, 'q> dot::GraphWalk<'a> for GraphvizDepGraph<'q> { + type Node = &'q DepNode; + type Edge = (&'q DepNode, &'q DepNode); + fn nodes(&self) -> dot::Nodes<&'q DepNode> { let nodes: Vec<_> = self.0.iter().cloned().collect(); nodes.into_cow() } - fn edges(&self) -> dot::Edges<(DepNode, DepNode)> { + fn edges(&self) -> dot::Edges<(&'q DepNode, &'q DepNode)> { self.1[..].into_cow() } - fn source(&self, edge: &(DepNode, DepNode)) -> DepNode { + fn source(&self, edge: &(&'q DepNode, &'q DepNode)) -> &'q DepNode { edge.0 } - fn target(&self, edge: &(DepNode, DepNode)) -> DepNode { + fn target(&self, edge: &(&'q DepNode, &'q DepNode)) -> &'q DepNode { edge.1 } } -impl<'a, 'tcx> dot::Labeller<'a> for GraphvizDepGraph { - type Node = DepNode; - type Edge = (DepNode, DepNode); +impl<'a, 'tcx, 'q> dot::Labeller<'a> for GraphvizDepGraph<'q> { + type Node = &'q DepNode; + type Edge = (&'q DepNode, &'q DepNode); fn graph_id(&self) -> dot::Id { dot::Id::new("DependencyGraph").unwrap() } - fn node_id(&self, n: &DepNode) -> dot::Id { + fn node_id(&self, n: &&'q DepNode) -> dot::Id { let s: String = format!("{:?}", n).chars() .map(|c| if c == '_' || c.is_alphanumeric() { c } else { '_' }) @@ -287,7 +287,7 @@ impl<'a, 'tcx> dot::Labeller<'a> for GraphvizDepGraph { debug!("n={:?} s={:?}", n, s); dot::Id::new(s).unwrap() } - fn node_label(&self, n: &DepNode) -> dot::LabelText { + fn node_label(&self, n: &&'q DepNode) -> dot::LabelText { dot::LabelText::label(format!("{:?}", n)) } } @@ -295,8 +295,8 @@ 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: &DepNodeFilter) - -> Option>> +fn node_set<'q>(query: &'q DepGraphQuery, filter: &DepNodeFilter) + -> Option>> { debug!("node_set(filter={:?})", filter); @@ -307,10 +307,10 @@ fn node_set(query: &DepGraphQuery, filter: &DepNodeFilter) Some(query.nodes().into_iter().filter(|n| filter.test(n)).collect()) } -fn filter_nodes(query: &DepGraphQuery, - sources: &Option>>, - targets: &Option>>) - -> FnvHashSet> +fn filter_nodes<'q>(query: &'q DepGraphQuery, + sources: &Option>>, + targets: &Option>>) + -> FnvHashSet<&'q DepNode> { if let &Some(ref sources) = sources { if let &Some(ref targets) = targets { @@ -325,21 +325,21 @@ fn filter_nodes(query: &DepGraphQuery, } } -fn walk_nodes(query: &DepGraphQuery, - starts: &FnvHashSet>, - direction: Direction) - -> FnvHashSet> +fn walk_nodes<'q>(query: &'q DepGraphQuery, + starts: &FnvHashSet<&'q DepNode>, + direction: Direction) + -> FnvHashSet<&'q DepNode> { let mut set = FnvHashSet(); - for start in starts { + for &start in starts { debug!("walk_nodes: start={:?} outgoing?={:?}", start, direction == OUTGOING); - if set.insert(*start) { + if set.insert(start) { let mut stack = vec![query.indices[start]]; while let Some(index) = stack.pop() { for (_, edge) in query.graph.adjacent_edges(index, direction) { let neighbor_index = edge.source_or_target(direction); let neighbor = query.graph.node_data(neighbor_index); - if set.insert(*neighbor) { + if set.insert(neighbor) { stack.push(neighbor_index); } } @@ -349,10 +349,10 @@ fn walk_nodes(query: &DepGraphQuery, set } -fn walk_between(query: &DepGraphQuery, - sources: &FnvHashSet>, - targets: &FnvHashSet>) - -> FnvHashSet> +fn walk_between<'q>(query: &'q DepGraphQuery, + sources: &FnvHashSet<&'q DepNode>, + targets: &FnvHashSet<&'q DepNode>) + -> FnvHashSet<&'q DepNode> { // This is a bit tricky. We want to include a node only if it is: // (a) reachable from a source and (b) will reach a target. And we @@ -365,16 +365,16 @@ fn walk_between(query: &DepGraphQuery, let mut node_states = vec![State::Undecided; query.graph.len_nodes()]; for &target in targets { - node_states[query.indices[&target].0] = State::Included; + node_states[query.indices[target].0] = State::Included; } - for source in sources.iter().map(|n| query.indices[n]) { + for source in sources.iter().map(|&n| query.indices[n]) { recurse(query, &mut node_states, source); } return query.nodes() .into_iter() - .filter(|n| { + .filter(|&n| { let index = query.indices[n]; node_states[index.0] == State::Included }) @@ -417,12 +417,12 @@ fn walk_between(query: &DepGraphQuery, } } -fn filter_edges(query: &DepGraphQuery, - nodes: &FnvHashSet>) - -> Vec<(DepNode, DepNode)> +fn filter_edges<'q>(query: &'q DepGraphQuery, + nodes: &FnvHashSet<&'q DepNode>) + -> Vec<(&'q DepNode, &'q DepNode)> { query.edges() .into_iter() - .filter(|&(source, target)| nodes.contains(&source) && nodes.contains(&target)) + .filter(|&(source, target)| nodes.contains(source) && nodes.contains(target)) .collect() } diff --git a/src/librustc_incremental/persist/directory.rs b/src/librustc_incremental/persist/directory.rs index f9e90f393219..2fd6973909a8 100644 --- a/src/librustc_incremental/persist/directory.rs +++ b/src/librustc_incremental/persist/directory.rs @@ -57,7 +57,7 @@ impl RetracedDefIdDirectory { self.ids[index.index as usize] } - pub fn map(&self, node: DepNode) -> Option> { + pub fn map(&self, node: &DepNode) -> Option> { node.map_def(|&index| self.def_id(index)) } } @@ -91,7 +91,7 @@ impl<'a,'tcx> DefIdDirectoryBuilder<'a,'tcx> { .clone() } - pub fn map(&mut self, node: DepNode) -> DepNode { + pub fn map(&mut self, node: &DepNode) -> DepNode { node.map_def(|&def_id| Some(self.add(def_id))).unwrap() } diff --git a/src/librustc_incremental/persist/hash.rs b/src/librustc_incremental/persist/hash.rs index b729f25b873d..99119dd184c8 100644 --- a/src/librustc_incremental/persist/hash.rs +++ b/src/librustc_incremental/persist/hash.rs @@ -39,8 +39,8 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { } } - pub fn hash(&mut self, dep_node: DepNode) -> Option { - match dep_node { + pub fn hash(&mut self, dep_node: &DepNode) -> Option { + match *dep_node { // HIR nodes (which always come from our crate) are an input: DepNode::Hir(def_id) => { assert!(def_id.is_local()); diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index e3fd290443c1..0ac1018462ee 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -114,15 +114,15 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let clean_nodes = serialized_dep_graph.nodes .iter() - .filter_map(|&node| retraced.map(node)) + .filter_map(|node| retraced.map(node)) .filter(|node| !dirty_nodes.contains(node)) - .map(|node| (node, node)); + .map(|node| (node.clone(), node)); // Add nodes and edges that are not dirty into our main graph. let dep_graph = tcx.dep_graph.clone(); for (source, target) in clean_edges.into_iter().chain(clean_nodes) { - let _task = dep_graph.in_task(target); - dep_graph.read(source); + let _task = dep_graph.in_task(target.clone()); + dep_graph.read(source.clone()); debug!("decode_dep_graph: clean edge: {:?} -> {:?}", source, target); } @@ -140,7 +140,7 @@ fn initial_dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, for hash in hashes { match hash.node.map_def(|&i| retraced.def_id(i)) { Some(dep_node) => { - let current_hash = hcx.hash(dep_node).unwrap(); + let current_hash = hcx.hash(&dep_node).unwrap(); debug!("initial_dirty_nodes: hash of {:?} is {:?}, was {:?}", dep_node, current_hash, hash.hash); if current_hash != hash.hash { @@ -171,7 +171,7 @@ fn compute_clean_edges(serialized_edges: &[(SerializedEdge)], // target) if neither node has been removed. If the source has // been removed, add target to the list of dirty nodes. let mut clean_edges = Vec::with_capacity(serialized_edges.len()); - for &(serialized_source, serialized_target) in serialized_edges { + for &(ref serialized_source, ref serialized_target) in serialized_edges { if let Some(target) = retraced.map(serialized_target) { if let Some(source) = retraced.map(serialized_source) { clean_edges.push((source, target)) diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index 7deb1ca36dbd..99f4d4f30729 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -99,7 +99,7 @@ pub fn encode_dep_graph<'a, 'tcx>(hcx: &mut HashContext<'a, 'tcx>, query.nodes() .into_iter() .filter_map(|dep_node| { - hcx.hash(dep_node) + hcx.hash(&dep_node) .map(|hash| { let node = builder.map(dep_node); SerializedHash { node: node, hash: hash } @@ -147,7 +147,7 @@ pub fn encode_metadata_hashes<'a, 'tcx>(hcx: &mut HashContext<'a, 'tcx>, let meta_data_def_ids = query.nodes() .into_iter() - .filter_map(|dep_node| match dep_node { + .filter_map(|dep_node| match *dep_node { DepNode::MetaData(def_id) if def_id.is_local() => Some(def_id), _ => None, }); @@ -165,8 +165,8 @@ pub fn encode_metadata_hashes<'a, 'tcx>(hcx: &mut HashContext<'a, 'tcx>, let dep_node = DepNode::MetaData(def_id); let mut state = SipHasher::new(); debug!("save: computing metadata hash for {:?}", dep_node); - for node in query.transitive_predecessors(dep_node) { - if let Some(hash) = hcx.hash(node) { + for node in query.transitive_predecessors(&dep_node) { + if let Some(hash) = hcx.hash(&node) { debug!("save: predecessor {:?} has hash {}", node, hash); state.write_u64(hash.to_le()); } else {