]> git.lizzy.rs Git - rust.git/blob - src/librustc_data_structures/obligation_forest/mod.rs
Rollup merge of #60187 - tmandry:generator-optimization, r=eddyb
[rust.git] / src / librustc_data_structures / obligation_forest / mod.rs
1 //! The `ObligationForest` is a utility data structure used in trait
2 //! matching to track the set of outstanding obligations (those not yet
3 //! resolved to success or error). It also tracks the "backtrace" of each
4 //! pending obligation (why we are trying to figure this out in the first
5 //! place).
6 //!
7 //! ### External view
8 //!
9 //! `ObligationForest` supports two main public operations (there are a
10 //! few others not discussed here):
11 //!
12 //! 1. Add a new root obligations (`push_tree`).
13 //! 2. Process the pending obligations (`process_obligations`).
14 //!
15 //! When a new obligation `N` is added, it becomes the root of an
16 //! obligation tree. This tree can also carry some per-tree state `T`,
17 //! which is given at the same time. This tree is a singleton to start, so
18 //! `N` is both the root and the only leaf. Each time the
19 //! `process_obligations` method is called, it will invoke its callback
20 //! with every pending obligation (so that will include `N`, the first
21 //! time). The callback also receives a (mutable) reference to the
22 //! per-tree state `T`. The callback should process the obligation `O`
23 //! that it is given and return one of three results:
24 //!
25 //! - `Ok(None)` -> ambiguous result. Obligation was neither a success
26 //!   nor a failure. It is assumed that further attempts to process the
27 //!   obligation will yield the same result unless something in the
28 //!   surrounding environment changes.
29 //! - `Ok(Some(C))` - the obligation was *shallowly successful*. The
30 //!   vector `C` is a list of subobligations. The meaning of this is that
31 //!   `O` was successful on the assumption that all the obligations in `C`
32 //!   are also successful. Therefore, `O` is only considered a "true"
33 //!   success if `C` is empty. Otherwise, `O` is put into a suspended
34 //!   state and the obligations in `C` become the new pending
35 //!   obligations. They will be processed the next time you call
36 //!   `process_obligations`.
37 //! - `Err(E)` -> obligation failed with error `E`. We will collect this
38 //!   error and return it from `process_obligations`, along with the
39 //!   "backtrace" of obligations (that is, the list of obligations up to
40 //!   and including the root of the failed obligation). No further
41 //!   obligations from that same tree will be processed, since the tree is
42 //!   now considered to be in error.
43 //!
44 //! When the call to `process_obligations` completes, you get back an `Outcome`,
45 //! which includes three bits of information:
46 //!
47 //! - `completed`: a list of obligations where processing was fully
48 //!   completed without error (meaning that all transitive subobligations
49 //!   have also been completed). So, for example, if the callback from
50 //!   `process_obligations` returns `Ok(Some(C))` for some obligation `O`,
51 //!   then `O` will be considered completed right away if `C` is the
52 //!   empty vector. Otherwise it will only be considered completed once
53 //!   all the obligations in `C` have been found completed.
54 //! - `errors`: a list of errors that occurred and associated backtraces
55 //!   at the time of error, which can be used to give context to the user.
56 //! - `stalled`: if true, then none of the existing obligations were
57 //!   *shallowly successful* (that is, no callback returned `Ok(Some(_))`).
58 //!   This implies that all obligations were either errors or returned an
59 //!   ambiguous result, which means that any further calls to
60 //!   `process_obligations` would simply yield back further ambiguous
61 //!   results. This is used by the `FulfillmentContext` to decide when it
62 //!   has reached a steady state.
63 //!
64 //! #### Snapshots
65 //!
66 //! The `ObligationForest` supports a limited form of snapshots; see
67 //! `start_snapshot`, `commit_snapshot`, and `rollback_snapshot`. In
68 //! particular, you can use a snapshot to roll back new root
69 //! obligations. However, it is an error to attempt to
70 //! `process_obligations` during a snapshot.
71 //!
72 //! ### Implementation details
73 //!
74 //! For the most part, comments specific to the implementation are in the
75 //! code. This file only contains a very high-level overview. Basically,
76 //! the forest is stored in a vector. Each element of the vector is a node
77 //! in some tree. Each node in the vector has the index of an (optional)
78 //! parent and (for convenience) its root (which may be itself). It also
79 //! has a current state, described by `NodeState`. After each
80 //! processing step, we compress the vector to remove completed and error
81 //! nodes, which aren't needed anymore.
82
83 use crate::fx::{FxHashMap, FxHashSet};
84
85 use std::cell::Cell;
86 use std::collections::hash_map::Entry;
87 use std::fmt::Debug;
88 use std::hash;
89 use std::marker::PhantomData;
90
91 mod node_index;
92 use self::node_index::NodeIndex;
93
94 mod graphviz;
95
96 #[cfg(test)]
97 mod test;
98
99 pub trait ForestObligation : Clone + Debug {
100     type Predicate : Clone + hash::Hash + Eq + Debug;
101
102     fn as_predicate(&self) -> &Self::Predicate;
103 }
104
105 pub trait ObligationProcessor {
106     type Obligation : ForestObligation;
107     type Error : Debug;
108
109     fn process_obligation(&mut self,
110                           obligation: &mut Self::Obligation)
111                           -> ProcessResult<Self::Obligation, Self::Error>;
112
113     /// As we do the cycle check, we invoke this callback when we
114     /// encounter an actual cycle. `cycle` is an iterator that starts
115     /// at the start of the cycle in the stack and walks **toward the
116     /// top**.
117     ///
118     /// In other words, if we had O1 which required O2 which required
119     /// O3 which required O1, we would give an iterator yielding O1,
120     /// O2, O3 (O1 is not yielded twice).
121     fn process_backedge<'c, I>(&mut self,
122                                cycle: I,
123                                _marker: PhantomData<&'c Self::Obligation>)
124         where I: Clone + Iterator<Item=&'c Self::Obligation>;
125 }
126
127 /// The result type used by `process_obligation`.
128 #[derive(Debug)]
129 pub enum ProcessResult<O, E> {
130     Unchanged,
131     Changed(Vec<O>),
132     Error(E),
133 }
134
135 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
136 struct ObligationTreeId(usize);
137
138 type ObligationTreeIdGenerator =
139     ::std::iter::Map<::std::ops::RangeFrom<usize>, fn(usize) -> ObligationTreeId>;
140
141 pub struct ObligationForest<O: ForestObligation> {
142     /// The list of obligations. In between calls to
143     /// `process_obligations`, this list only contains nodes in the
144     /// `Pending` or `Success` state (with a non-zero number of
145     /// incomplete children). During processing, some of those nodes
146     /// may be changed to the error state, or we may find that they
147     /// are completed (That is, `num_incomplete_children` drops to 0).
148     /// At the end of processing, those nodes will be removed by a
149     /// call to `compress`.
150     ///
151     /// At all times we maintain the invariant that every node appears
152     /// at a higher index than its parent. This is needed by the
153     /// backtrace iterator (which uses `split_at`).
154     nodes: Vec<Node<O>>,
155
156     /// A cache of predicates that have been successfully completed.
157     done_cache: FxHashSet<O::Predicate>,
158
159     /// An cache of the nodes in `nodes`, indexed by predicate.
160     waiting_cache: FxHashMap<O::Predicate, NodeIndex>,
161
162     scratch: Option<Vec<usize>>,
163
164     obligation_tree_id_generator: ObligationTreeIdGenerator,
165
166     /// Per tree error cache. This is used to deduplicate errors,
167     /// which is necessary to avoid trait resolution overflow in
168     /// some cases.
169     ///
170     /// See [this][details] for details.
171     ///
172     /// [details]: https://github.com/rust-lang/rust/pull/53255#issuecomment-421184780
173     error_cache: FxHashMap<ObligationTreeId, FxHashSet<O::Predicate>>,
174 }
175
176 #[derive(Debug)]
177 struct Node<O> {
178     obligation: O,
179     state: Cell<NodeState>,
180
181     /// The parent of a node - the original obligation of
182     /// which it is a subobligation. Except for error reporting,
183     /// it is just like any member of `dependents`.
184     parent: Option<NodeIndex>,
185
186     /// Obligations that depend on this obligation for their
187     /// completion. They must all be in a non-pending state.
188     dependents: Vec<NodeIndex>,
189
190     /// Identifier of the obligation tree to which this node belongs.
191     obligation_tree_id: ObligationTreeId,
192 }
193
194 /// The state of one node in some tree within the forest. This
195 /// represents the current state of processing for the obligation (of
196 /// type `O`) associated with this node.
197 ///
198 /// Outside of ObligationForest methods, nodes should be either Pending
199 /// or Waiting.
200 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
201 enum NodeState {
202     /// Obligations for which selection had not yet returned a
203     /// non-ambiguous result.
204     Pending,
205
206     /// This obligation was selected successfully, but may or
207     /// may not have subobligations.
208     Success,
209
210     /// This obligation was selected successfully, but it has
211     /// a pending subobligation.
212     Waiting,
213
214     /// This obligation, along with its subobligations, are complete,
215     /// and will be removed in the next collection.
216     Done,
217
218     /// This obligation was resolved to an error. Error nodes are
219     /// removed from the vector by the compression step.
220     Error,
221
222     /// This is a temporary state used in DFS loops to detect cycles,
223     /// it should not exist outside of these DFSes.
224     OnDfsStack,
225 }
226
227 #[derive(Debug)]
228 pub struct Outcome<O, E> {
229     /// Obligations that were completely evaluated, including all
230     /// (transitive) subobligations. Only computed if requested.
231     pub completed: Option<Vec<O>>,
232
233     /// Backtrace of obligations that were found to be in error.
234     pub errors: Vec<Error<O, E>>,
235
236     /// If true, then we saw no successful obligations, which means
237     /// there is no point in further iteration. This is based on the
238     /// assumption that when trait matching returns `Error` or
239     /// `Unchanged`, those results do not affect environmental
240     /// inference state. (Note that if we invoke `process_obligations`
241     /// with no pending obligations, stalled will be true.)
242     pub stalled: bool,
243 }
244
245 /// Should `process_obligations` compute the `Outcome::completed` field of its
246 /// result?
247 #[derive(PartialEq)]
248 pub enum DoCompleted {
249     No,
250     Yes,
251 }
252
253 #[derive(Debug, PartialEq, Eq)]
254 pub struct Error<O, E> {
255     pub error: E,
256     pub backtrace: Vec<O>,
257 }
258
259 impl<O: ForestObligation> ObligationForest<O> {
260     pub fn new() -> ObligationForest<O> {
261         ObligationForest {
262             nodes: vec![],
263             done_cache: Default::default(),
264             waiting_cache: Default::default(),
265             scratch: Some(vec![]),
266             obligation_tree_id_generator: (0..).map(|i| ObligationTreeId(i)),
267             error_cache: Default::default(),
268         }
269     }
270
271     /// Returns the total number of nodes in the forest that have not
272     /// yet been fully resolved.
273     pub fn len(&self) -> usize {
274         self.nodes.len()
275     }
276
277     /// Registers an obligation.
278     ///
279     /// This CAN be done in a snapshot
280     pub fn register_obligation(&mut self, obligation: O) {
281         // Ignore errors here - there is no guarantee of success.
282         let _ = self.register_obligation_at(obligation, None);
283     }
284
285     // returns Err(()) if we already know this obligation failed.
286     fn register_obligation_at(&mut self, obligation: O, parent: Option<NodeIndex>)
287                               -> Result<(), ()>
288     {
289         if self.done_cache.contains(obligation.as_predicate()) {
290             return Ok(());
291         }
292
293         match self.waiting_cache.entry(obligation.as_predicate().clone()) {
294             Entry::Occupied(o) => {
295                 debug!("register_obligation_at({:?}, {:?}) - duplicate of {:?}!",
296                        obligation, parent, o.get());
297                 let node = &mut self.nodes[o.get().get()];
298                 if let Some(parent) = parent {
299                     // If the node is already in `waiting_cache`, it's already
300                     // been marked with a parent. (It's possible that parent
301                     // has been cleared by `apply_rewrites`, though.) So just
302                     // dump `parent` into `node.dependents`... unless it's
303                     // already in `node.dependents` or `node.parent`.
304                     if !node.dependents.contains(&parent) && Some(parent) != node.parent {
305                         node.dependents.push(parent);
306                     }
307                 }
308                 if let NodeState::Error = node.state.get() {
309                     Err(())
310                 } else {
311                     Ok(())
312                 }
313             }
314             Entry::Vacant(v) => {
315                 debug!("register_obligation_at({:?}, {:?}) - ok, new index is {}",
316                        obligation, parent, self.nodes.len());
317
318                 let obligation_tree_id = match parent {
319                     Some(p) => {
320                         let parent_node = &self.nodes[p.get()];
321                         parent_node.obligation_tree_id
322                     }
323                     None => self.obligation_tree_id_generator.next().unwrap()
324                 };
325
326                 let already_failed =
327                     parent.is_some()
328                         && self.error_cache
329                             .get(&obligation_tree_id)
330                             .map(|errors| errors.contains(obligation.as_predicate()))
331                             .unwrap_or(false);
332
333                 if already_failed {
334                     Err(())
335                 } else {
336                     v.insert(NodeIndex::new(self.nodes.len()));
337                     self.nodes.push(Node::new(parent, obligation, obligation_tree_id));
338                     Ok(())
339                 }
340             }
341         }
342     }
343
344     /// Converts all remaining obligations to the given error.
345     ///
346     /// This cannot be done during a snapshot.
347     pub fn to_errors<E: Clone>(&mut self, error: E) -> Vec<Error<O, E>> {
348         let mut errors = vec![];
349         for index in 0..self.nodes.len() {
350             if let NodeState::Pending = self.nodes[index].state.get() {
351                 let backtrace = self.error_at(index);
352                 errors.push(Error {
353                     error: error.clone(),
354                     backtrace,
355                 });
356             }
357         }
358         let successful_obligations = self.compress(DoCompleted::Yes);
359         assert!(successful_obligations.unwrap().is_empty());
360         errors
361     }
362
363     /// Returns the set of obligations that are in a pending state.
364     pub fn map_pending_obligations<P, F>(&self, f: F) -> Vec<P>
365         where F: Fn(&O) -> P
366     {
367         self.nodes
368             .iter()
369             .filter(|n| n.state.get() == NodeState::Pending)
370             .map(|n| f(&n.obligation))
371             .collect()
372     }
373
374     fn insert_into_error_cache(&mut self, node_index: usize) {
375         let node = &self.nodes[node_index];
376
377         self.error_cache
378             .entry(node.obligation_tree_id)
379             .or_default()
380             .insert(node.obligation.as_predicate().clone());
381     }
382
383     /// Performs a pass through the obligation list. This must
384     /// be called in a loop until `outcome.stalled` is false.
385     ///
386     /// This _cannot_ be unrolled (presently, at least).
387     pub fn process_obligations<P>(&mut self, processor: &mut P, do_completed: DoCompleted)
388                                   -> Outcome<O, P::Error>
389         where P: ObligationProcessor<Obligation=O>
390     {
391         debug!("process_obligations(len={})", self.nodes.len());
392
393         let mut errors = vec![];
394         let mut stalled = true;
395
396         for index in 0..self.nodes.len() {
397             debug!("process_obligations: node {} == {:?}", index, self.nodes[index]);
398
399             let result = match self.nodes[index] {
400                 Node { ref state, ref mut obligation, .. } if state.get() == NodeState::Pending =>
401                     processor.process_obligation(obligation),
402                 _ => continue
403             };
404
405             debug!("process_obligations: node {} got result {:?}", index, result);
406
407             match result {
408                 ProcessResult::Unchanged => {
409                     // No change in state.
410                 }
411                 ProcessResult::Changed(children) => {
412                     // We are not (yet) stalled.
413                     stalled = false;
414                     self.nodes[index].state.set(NodeState::Success);
415
416                     for child in children {
417                         let st = self.register_obligation_at(
418                             child,
419                             Some(NodeIndex::new(index))
420                         );
421                         if let Err(()) = st {
422                             // error already reported - propagate it
423                             // to our node.
424                             self.error_at(index);
425                         }
426                     }
427                 }
428                 ProcessResult::Error(err) => {
429                     stalled = false;
430                     let backtrace = self.error_at(index);
431                     errors.push(Error {
432                         error: err,
433                         backtrace,
434                     });
435                 }
436             }
437         }
438
439         if stalled {
440             // There's no need to perform marking, cycle processing and compression when nothing
441             // changed.
442             return Outcome {
443                 completed: if do_completed == DoCompleted::Yes { Some(vec![]) } else { None },
444                 errors,
445                 stalled,
446             };
447         }
448
449         self.mark_as_waiting();
450         self.process_cycles(processor);
451
452         // Now we have to compress the result
453         let completed = self.compress(do_completed);
454
455         debug!("process_obligations: complete");
456
457         Outcome {
458             completed,
459             errors,
460             stalled,
461         }
462     }
463
464     /// Mark all `NodeState::Success` nodes as `NodeState::Done` and
465     /// report all cycles between them. This should be called
466     /// after `mark_as_waiting` marks all nodes with pending
467     /// subobligations as NodeState::Waiting.
468     fn process_cycles<P>(&mut self, processor: &mut P)
469         where P: ObligationProcessor<Obligation=O>
470     {
471         let mut stack = self.scratch.take().unwrap();
472         debug_assert!(stack.is_empty());
473
474         debug!("process_cycles()");
475
476         for index in 0..self.nodes.len() {
477             // For rustc-benchmarks/inflate-0.1.0 this state test is extremely
478             // hot and the state is almost always `Pending` or `Waiting`. It's
479             // a win to handle the no-op cases immediately to avoid the cost of
480             // the function call.
481             let state = self.nodes[index].state.get();
482             match state {
483                 NodeState::Waiting | NodeState::Pending | NodeState::Done | NodeState::Error => {},
484                 _ => self.find_cycles_from_node(&mut stack, processor, index),
485             }
486         }
487
488         debug!("process_cycles: complete");
489
490         debug_assert!(stack.is_empty());
491         self.scratch = Some(stack);
492     }
493
494     fn find_cycles_from_node<P>(&self, stack: &mut Vec<usize>,
495                                 processor: &mut P, index: usize)
496         where P: ObligationProcessor<Obligation=O>
497     {
498         let node = &self.nodes[index];
499         let state = node.state.get();
500         match state {
501             NodeState::OnDfsStack => {
502                 let index =
503                     stack.iter().rposition(|n| *n == index).unwrap();
504                 processor.process_backedge(stack[index..].iter().map(GetObligation(&self.nodes)),
505                                            PhantomData);
506             }
507             NodeState::Success => {
508                 node.state.set(NodeState::OnDfsStack);
509                 stack.push(index);
510                 for dependent in node.parent.iter().chain(node.dependents.iter()) {
511                     self.find_cycles_from_node(stack, processor, dependent.get());
512                 }
513                 stack.pop();
514                 node.state.set(NodeState::Done);
515             },
516             NodeState::Waiting | NodeState::Pending => {
517                 // this node is still reachable from some pending node. We
518                 // will get to it when they are all processed.
519             }
520             NodeState::Done | NodeState::Error => {
521                 // already processed that node
522             }
523         };
524     }
525
526     /// Returns a vector of obligations for `p` and all of its
527     /// ancestors, putting them into the error state in the process.
528     fn error_at(&mut self, p: usize) -> Vec<O> {
529         let mut error_stack = self.scratch.take().unwrap();
530         let mut trace = vec![];
531
532         let mut n = p;
533         loop {
534             self.nodes[n].state.set(NodeState::Error);
535             trace.push(self.nodes[n].obligation.clone());
536             error_stack.extend(self.nodes[n].dependents.iter().map(|x| x.get()));
537
538             // loop to the parent
539             match self.nodes[n].parent {
540                 Some(q) => n = q.get(),
541                 None => break
542             }
543         }
544
545         while let Some(i) = error_stack.pop() {
546             match self.nodes[i].state.get() {
547                 NodeState::Error => continue,
548                 _ => self.nodes[i].state.set(NodeState::Error),
549             }
550
551             let node = &self.nodes[i];
552
553             error_stack.extend(
554                 node.parent.iter().chain(node.dependents.iter()).map(|x| x.get())
555             );
556         }
557
558         self.scratch = Some(error_stack);
559         trace
560     }
561
562     #[inline]
563     fn mark_neighbors_as_waiting_from(&self, node: &Node<O>) {
564         for dependent in node.parent.iter().chain(node.dependents.iter()) {
565             self.mark_as_waiting_from(&self.nodes[dependent.get()]);
566         }
567     }
568
569     /// Marks all nodes that depend on a pending node as `NodeState::Waiting`.
570     fn mark_as_waiting(&self) {
571         for node in &self.nodes {
572             if node.state.get() == NodeState::Waiting {
573                 node.state.set(NodeState::Success);
574             }
575         }
576
577         for node in &self.nodes {
578             if node.state.get() == NodeState::Pending {
579                 self.mark_neighbors_as_waiting_from(node);
580             }
581         }
582     }
583
584     fn mark_as_waiting_from(&self, node: &Node<O>) {
585         match node.state.get() {
586             NodeState::Waiting | NodeState::Error | NodeState::OnDfsStack => return,
587             NodeState::Success => node.state.set(NodeState::Waiting),
588             NodeState::Pending | NodeState::Done => {},
589         }
590
591         self.mark_neighbors_as_waiting_from(node);
592     }
593
594     /// Compresses the vector, removing all popped nodes. This adjusts
595     /// the indices and hence invalidates any outstanding
596     /// indices. Cannot be used during a transaction.
597     ///
598     /// Beforehand, all nodes must be marked as `Done` and no cycles
599     /// on these nodes may be present. This is done by e.g., `process_cycles`.
600     #[inline(never)]
601     fn compress(&mut self, do_completed: DoCompleted) -> Option<Vec<O>> {
602         let nodes_len = self.nodes.len();
603         let mut node_rewrites: Vec<_> = self.scratch.take().unwrap();
604         node_rewrites.extend(0..nodes_len);
605         let mut dead_nodes = 0;
606
607         // Now move all popped nodes to the end. Try to keep the order.
608         //
609         // LOOP INVARIANT:
610         //     self.nodes[0..i - dead_nodes] are the first remaining nodes
611         //     self.nodes[i - dead_nodes..i] are all dead
612         //     self.nodes[i..] are unchanged
613         for i in 0..self.nodes.len() {
614             match self.nodes[i].state.get() {
615                 NodeState::Pending | NodeState::Waiting => {
616                     if dead_nodes > 0 {
617                         self.nodes.swap(i, i - dead_nodes);
618                         node_rewrites[i] -= dead_nodes;
619                     }
620                 }
621                 NodeState::Done => {
622                     // Avoid cloning the key (predicate) in case it exists in the waiting cache
623                     if let Some((predicate, _)) = self.waiting_cache
624                         .remove_entry(self.nodes[i].obligation.as_predicate())
625                     {
626                         self.done_cache.insert(predicate);
627                     } else {
628                         self.done_cache.insert(self.nodes[i].obligation.as_predicate().clone());
629                     }
630                     node_rewrites[i] = nodes_len;
631                     dead_nodes += 1;
632                 }
633                 NodeState::Error => {
634                     // We *intentionally* remove the node from the cache at this point. Otherwise
635                     // tests must come up with a different type on every type error they
636                     // check against.
637                     self.waiting_cache.remove(self.nodes[i].obligation.as_predicate());
638                     node_rewrites[i] = nodes_len;
639                     dead_nodes += 1;
640                     self.insert_into_error_cache(i);
641                 }
642                 NodeState::OnDfsStack | NodeState::Success => unreachable!()
643             }
644         }
645
646         // No compression needed.
647         if dead_nodes == 0 {
648             node_rewrites.truncate(0);
649             self.scratch = Some(node_rewrites);
650             return if do_completed == DoCompleted::Yes { Some(vec![]) } else { None };
651         }
652
653         // Pop off all the nodes we killed and extract the success
654         // stories.
655         let successful = if do_completed == DoCompleted::Yes {
656             Some((0..dead_nodes)
657                 .map(|_| self.nodes.pop().unwrap())
658                 .flat_map(|node| {
659                     match node.state.get() {
660                         NodeState::Error => None,
661                         NodeState::Done => Some(node.obligation),
662                         _ => unreachable!()
663                     }
664                 })
665                 .collect())
666         } else {
667             self.nodes.truncate(self.nodes.len() - dead_nodes);
668             None
669         };
670         self.apply_rewrites(&node_rewrites);
671
672         node_rewrites.truncate(0);
673         self.scratch = Some(node_rewrites);
674
675         successful
676     }
677
678     fn apply_rewrites(&mut self, node_rewrites: &[usize]) {
679         let nodes_len = node_rewrites.len();
680
681         for node in &mut self.nodes {
682             if let Some(index) = node.parent {
683                 let new_index = node_rewrites[index.get()];
684                 if new_index >= nodes_len {
685                     // parent dead due to error
686                     node.parent = None;
687                 } else {
688                     node.parent = Some(NodeIndex::new(new_index));
689                 }
690             }
691
692             let mut i = 0;
693             while i < node.dependents.len() {
694                 let new_index = node_rewrites[node.dependents[i].get()];
695                 if new_index >= nodes_len {
696                     node.dependents.swap_remove(i);
697                 } else {
698                     node.dependents[i] = NodeIndex::new(new_index);
699                     i += 1;
700                 }
701             }
702         }
703
704         let mut kill_list = vec![];
705         for (predicate, index) in &mut self.waiting_cache {
706             let new_index = node_rewrites[index.get()];
707             if new_index >= nodes_len {
708                 kill_list.push(predicate.clone());
709             } else {
710                 *index = NodeIndex::new(new_index);
711             }
712         }
713
714         for predicate in kill_list { self.waiting_cache.remove(&predicate); }
715     }
716 }
717
718 impl<O> Node<O> {
719     fn new(
720         parent: Option<NodeIndex>,
721         obligation: O,
722         obligation_tree_id: ObligationTreeId
723     ) -> Node<O> {
724         Node {
725             obligation,
726             state: Cell::new(NodeState::Pending),
727             parent,
728             dependents: vec![],
729             obligation_tree_id,
730         }
731     }
732 }
733
734 // I need a Clone closure
735 #[derive(Clone)]
736 struct GetObligation<'a, O>(&'a [Node<O>]);
737
738 impl<'a, 'b, O> FnOnce<(&'b usize,)> for GetObligation<'a, O> {
739     type Output = &'a O;
740     extern "rust-call" fn call_once(self, args: (&'b usize,)) -> &'a O {
741         &self.0[*args.0].obligation
742     }
743 }
744
745 impl<'a, 'b, O> FnMut<(&'b usize,)> for GetObligation<'a, O> {
746     extern "rust-call" fn call_mut(&mut self, args: (&'b usize,)) -> &'a O {
747         &self.0[*args.0].obligation
748     }
749 }