diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2016-05-26 06:11:16 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2016-05-31 19:59:57 -0400 |
| commit | 63bb0847bdf58d7d021735184a9dfd48138ad8ab (patch) | |
| tree | b45a0c617888f4119737c87c0e1c826a9ee23b9f /src | |
| parent | 5dc6a058b2ec05a18447308b224669c4a9726f3c (diff) | |
| download | rust-63bb0847bdf58d7d021735184a9dfd48138ad8ab.tar.gz rust-63bb0847bdf58d7d021735184a9dfd48138ad8ab.zip | |
expand `DepNode::TraitSelect` to include type ids
To handle the general case, we include a vector of def-ids, so that we can account for things like `(Foo, Bar)` which references both `Foo` and `Bar`. This means it is not Copy, so re-jigger some APIs to use borrowing more intelligently.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/dep_graph/dep_node.rs | 19 | ||||
| -rw-r--r-- | src/librustc/dep_graph/query.rs | 24 | ||||
| -rw-r--r-- | src/librustc/dep_graph/raii.rs | 4 | ||||
| -rw-r--r-- | src/librustc/dep_graph/visit.rs | 2 | ||||
| -rw-r--r-- | src/librustc/ty/mod.rs | 13 | ||||
| -rw-r--r-- | src/librustc_incremental/assert_dep_graph.rs | 80 | ||||
| -rw-r--r-- | src/librustc_incremental/persist/directory.rs | 4 | ||||
| -rw-r--r-- | src/librustc_incremental/persist/hash.rs | 4 | ||||
| -rw-r--r-- | src/librustc_incremental/persist/load.rs | 12 | ||||
| -rw-r--r-- | src/librustc_incremental/persist/save.rs | 8 |
10 files changed, 91 insertions, 79 deletions
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 84c84a7ed57..73b96651b05 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<D: Clone + Debug> { // The `D` type is "how definitions are identified". // During compilation, it is always `DefId`, but when serializing @@ -116,7 +125,7 @@ pub enum DepNode<D: Clone + Debug> { // which would yield an overly conservative dep-graph. TraitItems(D), ReprHints(D), - TraitSelect(D), + TraitSelect(D, Vec<D>), } impl<D: Clone + Debug> DepNode<D> { @@ -212,7 +221,11 @@ impl<D: Clone + Debug> DepNode<D> { 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 93248edb197..7a780c1d4ae 100644 --- a/src/librustc/dep_graph/query.rs +++ b/src/librustc/dep_graph/query.rs @@ -47,26 +47,26 @@ impl<D: Clone + Debug + Hash + Eq> DepGraphQuery<D> { self.indices.contains_key(&node) } - pub fn nodes(&self) -> Vec<DepNode<D>> { + pub fn nodes(&self) -> Vec<&DepNode<D>> { self.graph.all_nodes() .iter() - .map(|n| n.data.clone()) + .map(|n| &n.data) .collect() } - pub fn edges(&self) -> Vec<(DepNode<D>,DepNode<D>)> { + pub fn edges(&self) -> Vec<(&DepNode<D>,&DepNode<D>)> { 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<D>, direction: Direction) -> Vec<DepNode<D>> { - if let Some(&index) = self.indices.get(&node) { + fn reachable_nodes(&self, node: &DepNode<D>, direction: Direction) -> Vec<&DepNode<D>> { + 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<D: Clone + Debug + Hash + Eq> DepGraphQuery<D> { /// 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<D>) -> Vec<DepNode<D>> { + pub fn transitive_successors(&self, node: &DepNode<D>) -> Vec<&DepNode<D>> { self.reachable_nodes(node, OUTGOING) } /// All nodes that can reach `node`. - pub fn transitive_predecessors(&self, node: DepNode<D>) -> Vec<DepNode<D>> { + pub fn transitive_predecessors(&self, node: &DepNode<D>) -> Vec<&DepNode<D>> { self.reachable_nodes(node, INCOMING) } /// Just the outgoing edges from `node`. - pub fn immediate_successors(&self, node: DepNode<D>) -> Vec<DepNode<D>> { + pub fn immediate_successors(&self, node: &DepNode<D>) -> Vec<&DepNode<D>> { 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 13151d169fc..92cecabaa18 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<DefId>) -> 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 9133b4d22ee..5dd71db2f18 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 24f0671ce61..423d57cfb32 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<DefId> { - 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<AdtDefMaster<'tcx>>) { - 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 9dc50a63064..1c0274cdcca 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<DepNode<DefId>>, - Vec<(DepNode<DefId>, DepNode<DefId>)>); +pub struct GraphvizDepGraph<'q>(FnvHashSet<&'q DepNode<DefId>>, + Vec<(&'q DepNode<DefId>, &'q DepNode<DefId>)>); -impl<'a, 'tcx> dot::GraphWalk<'a> for GraphvizDepGraph { - type Node = DepNode<DefId>; - type Edge = (DepNode<DefId>, DepNode<DefId>); - fn nodes(&self) -> dot::Nodes<DepNode<DefId>> { +impl<'a, 'tcx, 'q> dot::GraphWalk<'a> for GraphvizDepGraph<'q> { + type Node = &'q DepNode<DefId>; + type Edge = (&'q DepNode<DefId>, &'q DepNode<DefId>); + fn nodes(&self) -> dot::Nodes<&'q DepNode<DefId>> { let nodes: Vec<_> = self.0.iter().cloned().collect(); nodes.into_cow() } - fn edges(&self) -> dot::Edges<(DepNode<DefId>, DepNode<DefId>)> { + fn edges(&self) -> dot::Edges<(&'q DepNode<DefId>, &'q DepNode<DefId>)> { self.1[..].into_cow() } - fn source(&self, edge: &(DepNode<DefId>, DepNode<DefId>)) -> DepNode<DefId> { + fn source(&self, edge: &(&'q DepNode<DefId>, &'q DepNode<DefId>)) -> &'q DepNode<DefId> { edge.0 } - fn target(&self, edge: &(DepNode<DefId>, DepNode<DefId>)) -> DepNode<DefId> { + fn target(&self, edge: &(&'q DepNode<DefId>, &'q DepNode<DefId>)) -> &'q DepNode<DefId> { edge.1 } } -impl<'a, 'tcx> dot::Labeller<'a> for GraphvizDepGraph { - type Node = DepNode<DefId>; - type Edge = (DepNode<DefId>, DepNode<DefId>); +impl<'a, 'tcx, 'q> dot::Labeller<'a> for GraphvizDepGraph<'q> { + type Node = &'q DepNode<DefId>; + type Edge = (&'q DepNode<DefId>, &'q DepNode<DefId>); fn graph_id(&self) -> dot::Id { dot::Id::new("DependencyGraph").unwrap() } - fn node_id(&self, n: &DepNode<DefId>) -> dot::Id { + fn node_id(&self, n: &&'q DepNode<DefId>) -> 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<DefId>) -> dot::LabelText { + fn node_label(&self, n: &&'q DepNode<DefId>) -> 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<DefId>, filter: &DepNodeFilter) - -> Option<FnvHashSet<DepNode<DefId>>> +fn node_set<'q>(query: &'q DepGraphQuery<DefId>, filter: &DepNodeFilter) + -> Option<FnvHashSet<&'q DepNode<DefId>>> { debug!("node_set(filter={:?})", filter); @@ -307,10 +307,10 @@ fn node_set(query: &DepGraphQuery<DefId>, filter: &DepNodeFilter) Some(query.nodes().into_iter().filter(|n| filter.test(n)).collect()) } -fn filter_nodes(query: &DepGraphQuery<DefId>, - sources: &Option<FnvHashSet<DepNode<DefId>>>, - targets: &Option<FnvHashSet<DepNode<DefId>>>) - -> FnvHashSet<DepNode<DefId>> +fn filter_nodes<'q>(query: &'q DepGraphQuery<DefId>, + sources: &Option<FnvHashSet<&'q DepNode<DefId>>>, + targets: &Option<FnvHashSet<&'q DepNode<DefId>>>) + -> FnvHashSet<&'q DepNode<DefId>> { if let &Some(ref sources) = sources { if let &Some(ref targets) = targets { @@ -325,21 +325,21 @@ fn filter_nodes(query: &DepGraphQuery<DefId>, } } -fn walk_nodes(query: &DepGraphQuery<DefId>, - starts: &FnvHashSet<DepNode<DefId>>, - direction: Direction) - -> FnvHashSet<DepNode<DefId>> +fn walk_nodes<'q>(query: &'q DepGraphQuery<DefId>, + starts: &FnvHashSet<&'q DepNode<DefId>>, + direction: Direction) + -> FnvHashSet<&'q DepNode<DefId>> { 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<DefId>, set } -fn walk_between(query: &DepGraphQuery<DefId>, - sources: &FnvHashSet<DepNode<DefId>>, - targets: &FnvHashSet<DepNode<DefId>>) - -> FnvHashSet<DepNode<DefId>> +fn walk_between<'q>(query: &'q DepGraphQuery<DefId>, + sources: &FnvHashSet<&'q DepNode<DefId>>, + targets: &FnvHashSet<&'q DepNode<DefId>>) + -> FnvHashSet<&'q DepNode<DefId>> { // 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<DefId>, 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<DefId>, } } -fn filter_edges(query: &DepGraphQuery<DefId>, - nodes: &FnvHashSet<DepNode<DefId>>) - -> Vec<(DepNode<DefId>, DepNode<DefId>)> +fn filter_edges<'q>(query: &'q DepGraphQuery<DefId>, + nodes: &FnvHashSet<&'q DepNode<DefId>>) + -> Vec<(&'q DepNode<DefId>, &'q DepNode<DefId>)> { 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 f9e90f39321..2fd6973909a 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<DefPathIndex>) -> Option<DepNode<DefId>> { + pub fn map(&self, node: &DepNode<DefPathIndex>) -> Option<DepNode<DefId>> { 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<DefId>) -> DepNode<DefPathIndex> { + pub fn map(&mut self, node: &DepNode<DefId>) -> DepNode<DefPathIndex> { 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 b729f25b873..99119dd184c 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<DefId>) -> Option<u64> { - match dep_node { + pub fn hash(&mut self, dep_node: &DepNode<DefId>) -> Option<u64> { + 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 e3fd290443c..0ac1018462e 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 7deb1ca36db..99f4d4f3072 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 { |
