about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNicholas Nethercote <nnethercote@mozilla.com>2018-04-19 15:13:20 +1000
committerNicholas Nethercote <nnethercote@mozilla.com>2018-06-08 09:00:17 +1000
commitb0440d359b0dab992e8f01d63523799a72c81285 (patch)
treed0012b134f27abb24bef1f2ab1323e189012fd9d
parentbe5f17ccff09569c2dd22df9330364a92fec2295 (diff)
downloadrust-b0440d359b0dab992e8f01d63523799a72c81285.tar.gz
rust-b0440d359b0dab992e8f01d63523799a72c81285.zip
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%.
-rw-r--r--src/librustc/traits/engine.rs4
-rw-r--r--src/librustc/traits/fulfill.rs4
-rw-r--r--src/librustc_data_structures/obligation_forest/mod.rs6
-rw-r--r--src/librustc_typeck/check/closure.rs2
4 files changed, 7 insertions, 9 deletions
diff --git a/src/librustc/traits/engine.rs b/src/librustc/traits/engine.rs
index 8eee6f35ab9..40d54885619 100644
--- a/src/librustc/traits/engine.rs
+++ b/src/librustc/traits/engine.rs
@@ -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> {
diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs
index 4447a2b6ed1..7c31d8cc060 100644
--- a/src/librustc/traits/fulfill.rs
+++ b/src/librustc/traits/fulfill.rs
@@ -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())
     }
 }
 
diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs
index 612f44f09cf..c3934c4e1b8 100644
--- a/src/librustc_data_structures/obligation_forest/mod.rs
+++ b/src/librustc_data_structures/obligation_forest/mod.rs
@@ -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()
     }
 
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index 67245bec7fb..439c1b34227 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -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)),