Skip to content

Commit b0440d3

Browse files
committed
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%.
1 parent be5f17c commit b0440d3

File tree

4 files changed

+7
-9
lines changed

4 files changed

+7
-9
lines changed

src/librustc/traits/engine.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use ty::{self, Ty, TyCtxt};
1313
use hir::def_id::DefId;
1414

1515
use super::{FulfillmentContext, FulfillmentError};
16-
use super::{ObligationCause, PendingPredicateObligation, PredicateObligation};
16+
use super::{ObligationCause, PredicateObligation};
1717

1818
pub trait TraitEngine<'tcx>: 'tcx {
1919
fn normalize_projection_type<'a, 'gcx>(
@@ -49,7 +49,7 @@ pub trait TraitEngine<'tcx>: 'tcx {
4949
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
5050
) -> Result<(), Vec<FulfillmentError<'tcx>>>;
5151

52-
fn pending_obligations(&self) -> Vec<PendingPredicateObligation<'tcx>>;
52+
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>;
5353
}
5454

5555
impl<'a, 'gcx, 'tcx> dyn TraitEngine<'tcx> {

src/librustc/traits/fulfill.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,8 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
241241
self.select(&mut selcx)
242242
}
243243

244-
fn pending_obligations(&self) -> Vec<PendingPredicateObligation<'tcx>> {
245-
self.predicates.pending_obligations()
244+
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
245+
self.predicates.map_pending_obligations(|o| o.obligation.clone())
246246
}
247247
}
248248

src/librustc_data_structures/obligation_forest/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,13 +229,13 @@ impl<O: ForestObligation> ObligationForest<O> {
229229
}
230230

231231
/// Returns the set of obligations that are in a pending state.
232-
pub fn pending_obligations(&self) -> Vec<O>
233-
where O: Clone
232+
pub fn map_pending_obligations<P, F>(&self, f: F) -> Vec<P>
233+
where F: Fn(&O) -> P
234234
{
235235
self.nodes
236236
.iter()
237237
.filter(|n| n.state.get() == NodeState::Pending)
238-
.map(|n| n.obligation.clone())
238+
.map(|n| f(&n.obligation))
239239
.collect()
240240
}
241241

src/librustc_typeck/check/closure.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
225225
let expected_sig = fulfillment_cx
226226
.pending_obligations()
227227
.iter()
228-
.map(|obligation| &obligation.obligation)
229228
.filter_map(|obligation| {
230229
debug!(
231230
"deduce_expectations_from_obligations: obligation.predicate={:?}",
@@ -257,7 +256,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
257256
let expected_kind = fulfillment_cx
258257
.pending_obligations()
259258
.iter()
260-
.map(|obligation| &obligation.obligation)
261259
.filter_map(|obligation| {
262260
let opt_trait_ref = match obligation.predicate {
263261
ty::Predicate::Projection(ref data) => Some(data.to_poly_trait_ref(self.tcx)),

0 commit comments

Comments
 (0)