diff options
Diffstat (limited to '')
-rw-r--r-- | compiler/rustc_data_structures/src/obligation_forest/mod.rs | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs index 07a96dd7d..10e673cd9 100644 --- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs +++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs @@ -95,6 +95,10 @@ pub trait ForestObligation: Clone + Debug { pub trait ObligationProcessor { type Obligation: ForestObligation; type Error: Debug; + type OUT: OutcomeTrait< + Obligation = Self::Obligation, + Error = Error<Self::Obligation, Self::Error>, + >; fn needs_process_obligation(&self, obligation: &Self::Obligation) -> bool; @@ -111,12 +115,20 @@ pub trait ObligationProcessor { /// In other words, if we had O1 which required O2 which required /// O3 which required O1, we would give an iterator yielding O1, /// O2, O3 (O1 is not yielded twice). - fn process_backedge<'c, I>(&mut self, cycle: I, _marker: PhantomData<&'c Self::Obligation>) + fn process_backedge<'c, I>( + &mut self, + cycle: I, + _marker: PhantomData<&'c Self::Obligation>, + ) -> Result<(), Self::Error> where I: Clone + Iterator<Item = &'c Self::Obligation>; } /// The result type used by `process_obligation`. +// `repr(C)` to inhibit the niche filling optimization. Otherwise, the `match` appearing +// in `process_obligations` is significantly slower, which can substantially affect +// benchmarks like `rustc-perf`'s inflate and keccak. +#[repr(C)] #[derive(Debug)] pub enum ProcessResult<O, E> { Unchanged, @@ -398,12 +410,11 @@ impl<O: ForestObligation> ObligationForest<O> { /// Performs a fixpoint computation over the obligation list. #[inline(never)] - pub fn process_obligations<P, OUT>(&mut self, processor: &mut P) -> OUT + pub fn process_obligations<P>(&mut self, processor: &mut P) -> P::OUT where P: ObligationProcessor<Obligation = O>, - OUT: OutcomeTrait<Obligation = O, Error = Error<O, P::Error>>, { - let mut outcome = OUT::new(); + let mut outcome = P::OUT::new(); // Fixpoint computation: we repeat until the inner loop stalls. loop { @@ -469,7 +480,7 @@ impl<O: ForestObligation> ObligationForest<O> { } self.mark_successes(); - self.process_cycles(processor); + self.process_cycles(processor, &mut outcome); self.compress(|obl| outcome.record_completed(obl)); } @@ -554,7 +565,7 @@ impl<O: ForestObligation> ObligationForest<O> { /// Report cycles between all `Success` nodes, and convert all `Success` /// nodes to `Done`. This must be called after `mark_successes`. - fn process_cycles<P>(&mut self, processor: &mut P) + fn process_cycles<P>(&mut self, processor: &mut P, outcome: &mut P::OUT) where P: ObligationProcessor<Obligation = O>, { @@ -564,7 +575,7 @@ impl<O: ForestObligation> ObligationForest<O> { // to handle the no-op cases immediately to avoid the cost of the // function call. if node.state.get() == NodeState::Success { - self.find_cycles_from_node(&mut stack, processor, index); + self.find_cycles_from_node(&mut stack, processor, index, outcome); } } @@ -572,8 +583,13 @@ impl<O: ForestObligation> ObligationForest<O> { self.reused_node_vec = stack; } - fn find_cycles_from_node<P>(&self, stack: &mut Vec<usize>, processor: &mut P, index: usize) - where + fn find_cycles_from_node<P>( + &self, + stack: &mut Vec<usize>, + processor: &mut P, + index: usize, + outcome: &mut P::OUT, + ) where P: ObligationProcessor<Obligation = O>, { let node = &self.nodes[index]; @@ -582,17 +598,20 @@ impl<O: ForestObligation> ObligationForest<O> { None => { stack.push(index); for &dep_index in node.dependents.iter() { - self.find_cycles_from_node(stack, processor, dep_index); + self.find_cycles_from_node(stack, processor, dep_index, outcome); } stack.pop(); node.state.set(NodeState::Done); } Some(rpos) => { // Cycle detected. - processor.process_backedge( + let result = processor.process_backedge( stack[rpos..].iter().map(|&i| &self.nodes[i].obligation), PhantomData, ); + if let Err(err) = result { + outcome.record_error(Error { error: err, backtrace: self.error_at(index) }); + } } } } |