summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_data_structures/src/obligation_forest/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--compiler/rustc_data_structures/src/obligation_forest/mod.rs41
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) });
+ }
}
}
}