Skip to content

Commit dbc3c6e

Browse files
committed
Make process_obligations' computation of completed optional.
It's only used in tests. This reduces instruction counts on several benchmarks by 0.5--1%.
1 parent d586d5d commit dbc3c6e

File tree

3 files changed

+88
-72
lines changed

3 files changed

+88
-72
lines changed

src/librustc/traits/fulfill.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ use infer::InferCtxt;
1212
use mir::interpret::{GlobalId, ErrorHandled};
1313
use ty::{self, Ty, TypeFoldable, ToPolyTraitRef, ToPredicate};
1414
use ty::error::ExpectedFound;
15-
use rustc_data_structures::obligation_forest::{Error, ForestObligation, ObligationForest};
16-
use rustc_data_structures::obligation_forest::{ObligationProcessor, ProcessResult};
15+
use rustc_data_structures::obligation_forest::{DoCompleted, Error, ForestObligation};
16+
use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
17+
use rustc_data_structures::obligation_forest::{ProcessResult};
1718
use std::marker::PhantomData;
1819
use hir::def_id::DefId;
1920

@@ -98,7 +99,7 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
9899
let outcome = self.predicates.process_obligations(&mut FulfillProcessor {
99100
selcx,
100101
register_region_obligations: self.register_region_obligations
101-
});
102+
}, DoCompleted::No);
102103
debug!("select: outcome={:#?}", outcome);
103104

104105
// FIXME: if we kept the original cache key, we could mark projection

src/librustc_data_structures/obligation_forest/mod.rs

+34-20
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,8 @@ enum NodeState {
162162
#[derive(Debug)]
163163
pub struct Outcome<O, E> {
164164
/// Obligations that were completely evaluated, including all
165-
/// (transitive) subobligations.
166-
pub completed: Vec<O>,
165+
/// (transitive) subobligations. Only computed if requested.
166+
pub completed: Option<Vec<O>>,
167167

168168
/// Backtrace of obligations that were found to be in error.
169169
pub errors: Vec<Error<O, E>>,
@@ -177,6 +177,14 @@ pub struct Outcome<O, E> {
177177
pub stalled: bool,
178178
}
179179

180+
/// Should `process_obligations` compute the `Outcome::completed` field of its
181+
/// result?
182+
#[derive(PartialEq)]
183+
pub enum DoCompleted {
184+
No,
185+
Yes,
186+
}
187+
180188
#[derive(Debug, PartialEq, Eq)]
181189
pub struct Error<O, E> {
182190
pub error: E,
@@ -282,8 +290,8 @@ impl<O: ForestObligation> ObligationForest<O> {
282290
});
283291
}
284292
}
285-
let successful_obligations = self.compress();
286-
assert!(successful_obligations.is_empty());
293+
let successful_obligations = self.compress(DoCompleted::Yes);
294+
assert!(successful_obligations.unwrap().is_empty());
287295
errors
288296
}
289297

@@ -311,7 +319,8 @@ impl<O: ForestObligation> ObligationForest<O> {
311319
/// be called in a loop until `outcome.stalled` is false.
312320
///
313321
/// This CANNOT be unrolled (presently, at least).
314-
pub fn process_obligations<P>(&mut self, processor: &mut P) -> Outcome<O, P::Error>
322+
pub fn process_obligations<P>(&mut self, processor: &mut P, do_completed: DoCompleted)
323+
-> Outcome<O, P::Error>
315324
where P: ObligationProcessor<Obligation=O>
316325
{
317326
debug!("process_obligations(len={})", self.nodes.len());
@@ -366,7 +375,7 @@ impl<O: ForestObligation> ObligationForest<O> {
366375
// There's no need to perform marking, cycle processing and compression when nothing
367376
// changed.
368377
return Outcome {
369-
completed: vec![],
378+
completed: if do_completed == DoCompleted::Yes { Some(vec![]) } else { None },
370379
errors,
371380
stalled,
372381
};
@@ -376,12 +385,12 @@ impl<O: ForestObligation> ObligationForest<O> {
376385
self.process_cycles(processor);
377386

378387
// Now we have to compress the result
379-
let completed_obligations = self.compress();
388+
let completed = self.compress(do_completed);
380389

381390
debug!("process_obligations: complete");
382391

383392
Outcome {
384-
completed: completed_obligations,
393+
completed,
385394
errors,
386395
stalled,
387396
}
@@ -524,7 +533,7 @@ impl<O: ForestObligation> ObligationForest<O> {
524533
/// Beforehand, all nodes must be marked as `Done` and no cycles
525534
/// on these nodes may be present. This is done by e.g. `process_cycles`.
526535
#[inline(never)]
527-
fn compress(&mut self) -> Vec<O> {
536+
fn compress(&mut self, do_completed: DoCompleted) -> Option<Vec<O>> {
528537
let nodes_len = self.nodes.len();
529538
let mut node_rewrites: Vec<_> = self.scratch.take().unwrap();
530539
node_rewrites.extend(0..nodes_len);
@@ -573,21 +582,26 @@ impl<O: ForestObligation> ObligationForest<O> {
573582
if dead_nodes == 0 {
574583
node_rewrites.truncate(0);
575584
self.scratch = Some(node_rewrites);
576-
return vec![];
585+
return if do_completed == DoCompleted::Yes { Some(vec![]) } else { None };
577586
}
578587

579588
// Pop off all the nodes we killed and extract the success
580589
// stories.
581-
let successful = (0..dead_nodes)
582-
.map(|_| self.nodes.pop().unwrap())
583-
.flat_map(|node| {
584-
match node.state.get() {
585-
NodeState::Error => None,
586-
NodeState::Done => Some(node.obligation),
587-
_ => unreachable!()
588-
}
589-
})
590-
.collect();
590+
let successful = if do_completed == DoCompleted::Yes {
591+
Some((0..dead_nodes)
592+
.map(|_| self.nodes.pop().unwrap())
593+
.flat_map(|node| {
594+
match node.state.get() {
595+
NodeState::Error => None,
596+
NodeState::Done => Some(node.obligation),
597+
_ => unreachable!()
598+
}
599+
})
600+
.collect())
601+
} else {
602+
self.nodes.truncate(self.nodes.len() - dead_nodes);
603+
None
604+
};
591605
self.apply_rewrites(&node_rewrites);
592606

593607
node_rewrites.truncate(0);

0 commit comments

Comments
 (0)