Rollup merge of #51412 - nnethercote:pending_obligations, r=estebank

Avoid useless Vec clones in pending_obligations().

The only instance of `ObligationForest` in use has an obligation type of
`PendingPredicateObligation`, which contains a `PredicateObligation` and a
`Vec<Ty>`.

`FulfillmentContext::pending_obligations()` calls
`ObligationForest::pending_obligations()`, which clones all the
`PendingPredicateObligation`s. But the `Vec<Ty>` field of those cloned
obligations is never touched.

This patch changes `ObligationForest::pending_obligations()` to
`map_pending_obligations` -- which gives callers control about which part
of the obligation to clone -- and takes advantage of the change to avoid
cloning the `Vec<Ty>`. The change speeds up runs of a few rustc-perf
benchmarks, the best by 1%.
This commit is contained in:
Mark Rousskov 2018-06-08 17:21:07 -06:00 committed by GitHub
commit 8ac351c209
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 7 additions and 9 deletions

View File

@ -13,7 +13,7 @@ use ty::{self, Ty, TyCtxt};
use hir::def_id::DefId;
use super::{FulfillmentContext, FulfillmentError};
use super::{ObligationCause, PendingPredicateObligation, PredicateObligation};
use super::{ObligationCause, PredicateObligation};
pub trait TraitEngine<'tcx>: 'tcx {
fn normalize_projection_type<'a, 'gcx>(
@ -49,7 +49,7 @@ pub trait TraitEngine<'tcx>: 'tcx {
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
) -> Result<(), Vec<FulfillmentError<'tcx>>>;
fn pending_obligations(&self) -> Vec<PendingPredicateObligation<'tcx>>;
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>;
}
impl<'a, 'gcx, 'tcx> dyn TraitEngine<'tcx> {

View File

@ -241,8 +241,8 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
self.select(&mut selcx)
}
fn pending_obligations(&self) -> Vec<PendingPredicateObligation<'tcx>> {
self.predicates.pending_obligations()
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
self.predicates.map_pending_obligations(|o| o.obligation.clone())
}
}

View File

@ -229,13 +229,13 @@ impl<O: ForestObligation> ObligationForest<O> {
}
/// Returns the set of obligations that are in a pending state.
pub fn pending_obligations(&self) -> Vec<O>
where O: Clone
pub fn map_pending_obligations<P, F>(&self, f: F) -> Vec<P>
where F: Fn(&O) -> P
{
self.nodes
.iter()
.filter(|n| n.state.get() == NodeState::Pending)
.map(|n| n.obligation.clone())
.map(|n| f(&n.obligation))
.collect()
}

View File

@ -225,7 +225,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let expected_sig = fulfillment_cx
.pending_obligations()
.iter()
.map(|obligation| &obligation.obligation)
.filter_map(|obligation| {
debug!(
"deduce_expectations_from_obligations: obligation.predicate={:?}",
@ -257,7 +256,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let expected_kind = fulfillment_cx
.pending_obligations()
.iter()
.map(|obligation| &obligation.obligation)
.filter_map(|obligation| {
let opt_trait_ref = match obligation.predicate {
ty::Predicate::Projection(ref data) => Some(data.to_poly_trait_ref(self.tcx)),