]> git.lizzy.rs Git - rust.git/commitdiff
Simplify `process_obligation`.
authorNicholas Nethercote <nnethercote@mozilla.com>
Wed, 6 Jun 2018 22:31:57 +0000 (08:31 +1000)
committerNicholas Nethercote <nnethercote@mozilla.com>
Thu, 7 Jun 2018 10:25:05 +0000 (20:25 +1000)
`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%.

src/librustc/traits/fulfill.rs

index dff89f3c888a73d54e5fcb17348b625d943347a2..b8ed9da8fce90f8f7878b01e9a2bd07d47e2bc62 100644 (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 @@ fn process_obligation(&mut self,
                           -> 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,