]> git.lizzy.rs Git - rust.git/commitdiff
expand `DepNode::TraitSelect` to include type ids
authorNiko Matsakis <niko@alum.mit.edu>
Thu, 26 May 2016 10:11:16 +0000 (06:11 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Tue, 31 May 2016 23:59:57 +0000 (19:59 -0400)
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.

src/librustc/dep_graph/dep_node.rs
src/librustc/dep_graph/query.rs
src/librustc/dep_graph/raii.rs
src/librustc/dep_graph/visit.rs
src/librustc/ty/mod.rs
src/librustc_incremental/assert_dep_graph.rs
src/librustc_incremental/persist/directory.rs
src/librustc_incremental/persist/hash.rs
src/librustc_incremental/persist/load.rs
src/librustc_incremental/persist/save.rs

index 84c84a7ed57a2656af76de3a0a0428d53c0d10f3..73b96651b05e27826c031d55267cff16415a7bf1 100644 (file)
 
 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 @@ pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
             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))
+            }
         }
     }
 }
index 93248edb197c625e9f4fec25559171ff4245ece5..7a780c1d4ae2478bc6d80d2e9c932bb0063e4b1e 100644 (file)
@@ -47,26 +47,26 @@ pub fn contains_node(&self, node: &DepNode<D>) -> bool {
         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 @@ fn reachable_nodes(&self, node: DepNode<D>, direction: Direction) -> Vec<DepNode
 
     /// 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![]
index 13151d169fc3f78843405d5a1829ec9d2823d985..92cecabaa182f86cadf45b1488504d9ea5245f86 100644 (file)
@@ -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()));
     }
 }
 
index 9133b4d22eeb2ec0693757d90045b6f8e0140817..5dd71db2f1832870b8e87171499b772c32acf02e 100644 (file)
@@ -39,7 +39,7 @@ impl<'visit, 'tcx, F, V> Visitor<'tcx> for TrackingVisitor<'visit, 'tcx, F, V>
         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);
index 24f0671ce6184c2c03a396653ecb9a329df81421..423d57cfb328d4c110a2ffabb72e1f3c4c7197df 100644 (file)
@@ -946,7 +946,7 @@ pub fn def_id(&self) -> DefId {
 
     /// 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 @@ fn calculate_sized_constraint_inner(&'tcx self, tcx: TyCtxt<'a, '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 @@ fn calculate_sized_constraint_inner(&'tcx self, tcx: TyCtxt<'a, '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 @@ fn calculate_sized_constraint_inner(&'tcx self, tcx: TyCtxt<'a, '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)
             }
         }
     }
index 9dc50a6306406d8684afcab039c98331e75f4417..1c0274cdcca9a68bf19d5cf8c431b8e0a64fca4e 100644 (file)
@@ -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 @@ fn node_id(&self, n: &DepNode<DefId>) -> dot::Id {
         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 @@ 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: &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 @@ enum State { Undecided, Deciding, Included, Excluded }
     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 recurse(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()
 }
index f9e90f393219dcc7d6462d16628a55d576e46004..2fd6973909a8ec59c33a146658b60913049be8a2 100644 (file)
@@ -57,7 +57,7 @@ pub fn def_id(&self, index: DefPathIndex) -> Option<DefId> {
         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 @@ pub fn add(&mut self, def_id: DefId) -> DefPathIndex {
                  .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()
     }
 
index b729f25b873d4f05ec8df2b45e7239c4cb02fa7f..99119dd184c8b3929045d5e75afa08134e3a776a 100644 (file)
@@ -39,8 +39,8 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
         }
     }
 
-    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());
index e3fd290443c11bf38ceb002c0bb23d2400b0f748..0ac1018462ee7a7eb06a2e6cc2b75a01eacda4db 100644 (file)
@@ -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))
index 7deb1ca36dbded0451760ab5e15ac870434bbcc7..99f4d4f3072989b6b74a4c561bd9f32f086a0871 100644 (file)
@@ -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 {