Simplify process_obligation.

`process_predicates` returns a
`Result<Option<Vec<PredicateObligation>>>`. `process_obligation` calls
it and then fiddles with the output (using `map`, `map`, `into_iter`,
`collect`) to produce a a
`Result<Option<Vec<PendingPredicateObligation>>>`.

This function is sufficiently hot that the fiddling is expensive. It's
much better for `process_predicate` to directly return a
`Result<Option<Vec<PendingPredicateObligation>>>` because `Ok(None)`
accounts for ~90% of the results, and `Ok(vec![])` accounts for another
~5%.
This commit is contained in:
Nicholas Nethercote 2018-06-07 08:31:57 +10:00
parent c131bdcaff
commit cdfd9ca088

View file

@ -251,6 +251,13 @@ struct FulfillProcessor<'a, 'b: 'a, 'gcx: 'tcx, 'tcx: 'b> {
register_region_obligations: bool
}
fn mk_pending(os: Vec<PredicateObligation<'tcx>>) -> Vec<PendingPredicateObligation<'tcx>> {
os.into_iter().map(|o| PendingPredicateObligation {
obligation: o,
stalled_on: vec![]
}).collect()
}
impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx, 'tcx> {
type Obligation = PendingPredicateObligation<'tcx>;
type Error = FulfillmentErrorCode<'tcx>;
@ -260,10 +267,6 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx,
-> Result<Option<Vec<Self::Obligation>>, Self::Error>
{
process_predicate(self.selcx, obligation, self.register_region_obligations)
.map(|os| os.map(|os| os.into_iter().map(|o| PendingPredicateObligation {
obligation: o,
stalled_on: vec![]
}).collect()))
}
fn process_backedge<'c, I>(&mut self, cycle: I,
@ -300,7 +303,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
selcx: &mut SelectionContext<'a, 'gcx, 'tcx>,
pending_obligation: &mut PendingPredicateObligation<'tcx>,
register_region_obligations: bool)
-> Result<Option<Vec<PredicateObligation<'tcx>>>,
-> Result<Option<Vec<PendingPredicateObligation<'tcx>>>,
FulfillmentErrorCode<'tcx>>
{
// if we were stalled on some unresolved variables, first check
@ -343,7 +346,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
Ok(Some(vtable)) => {
debug!("selecting trait `{:?}` at depth {} yielded Ok(Some)",
data, obligation.recursion_depth);
Ok(Some(vtable.nested_obligations()))
Ok(Some(mk_pending(vtable.nested_obligations())))
}
Ok(None) => {
debug!("selecting trait `{:?}` at depth {} yielded Ok(None)",
@ -444,7 +447,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
trait_ref_type_vars(selcx, data.to_poly_trait_ref(tcx));
Ok(None)
}
Ok(v) => Ok(v),
Ok(Some(os)) => Ok(Some(mk_pending(os))),
Err(e) => Err(CodeProjectionError(e))
}
}
@ -481,7 +484,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
pending_obligation.stalled_on = vec![ty];
Ok(None)
}
s => Ok(s)
Some(os) => Ok(Some(mk_pending(os)))
}
}
@ -496,7 +499,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
Ok(None)
}
Some(Ok(ok)) => {
Ok(Some(ok.obligations))
Ok(Some(mk_pending(ok.obligations)))
}
Some(Err(err)) => {
let expected_found = ExpectedFound::new(subtype.skip_binder().a_is_expected,