about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNicholas Nethercote <nnethercote@mozilla.com>2019-12-06 16:57:57 +1100
committerNicholas Nethercote <nnethercote@mozilla.com>2019-12-11 10:03:46 +1100
commit21f35bc26f1ffccf30916b7d6930d1526172f2da (patch)
tree059fa9a632cb416df6dbe4e4bec14cc76b5e27e8
parentf5e68ccd09c774c4395ad0eed0b171b5f1cf678b (diff)
downloadrust-21f35bc26f1ffccf30916b7d6930d1526172f2da.tar.gz
rust-21f35bc26f1ffccf30916b7d6930d1526172f2da.zip
Change `PendingPredicateObligation::stalled_on`'s type.
From a `Vec<Ty>` to a `Vec<InferTy>`, because that's a more restrictive
type. This is a perf win because the ultra-hot function
`shallow_resolve_changed` has less pattern-matching to do.
-rw-r--r--src/librustc/infer/mod.rs16
-rw-r--r--src/librustc/traits/fulfill.rs30
2 files changed, 26 insertions, 20 deletions
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index fca7704d5ee..73977878af3 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -1617,30 +1617,28 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
     // `resolver.shallow_resolve(ty) != ty`, but more efficient. It's always
     // inlined, despite being large, because it has only two call sites that
     // are extremely hot.
-    //
-    // Note that `typ` is always a `ty::Infer(_)`.
     #[inline(always)]
-    pub fn shallow_resolve_changed(&self, typ: Ty<'tcx>) -> bool {
-        match typ.kind {
-            ty::Infer(ty::TyVar(v)) => {
+    pub fn shallow_resolve_changed(&self, infer: ty::InferTy) -> bool {
+        match infer {
+            ty::TyVar(v) => {
                 use self::type_variable::TypeVariableValue;
 
-                // If `inlined_probe` returns a `Known` value it never matches
-                // `typ`.
+                // If `inlined_probe` returns a `Known` value its `kind` never
+                // matches `infer`.
                 match self.infcx.type_variables.borrow_mut().inlined_probe(v) {
                     TypeVariableValue::Unknown { .. } => false,
                     TypeVariableValue::Known { .. } => true,
                 }
             }
 
-            ty::Infer(ty::IntVar(v)) => {
+            ty::IntVar(v) => {
                 // If inlined_probe_value returns a value it's always a
                 // `ty::Int(_)` or `ty::UInt(_)`, which nevers matches a
                 // `ty::Infer(_)`.
                 self.infcx.int_unification_table.borrow_mut().inlined_probe_value(v).is_some()
             }
 
-            ty::Infer(ty::FloatVar(v)) => {
+            ty::FloatVar(v) => {
                 // If inlined_probe_value returns a value it's always a
                 // `ty::Float(_)`, which nevers matches a `ty::Infer(_)`.
                 //
diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs
index a981162fdc3..27731990d2b 100644
--- a/src/librustc/traits/fulfill.rs
+++ b/src/librustc/traits/fulfill.rs
@@ -65,7 +65,7 @@ pub struct FulfillmentContext<'tcx> {
 #[derive(Clone, Debug)]
 pub struct PendingPredicateObligation<'tcx> {
     pub obligation: PredicateObligation<'tcx>,
-    pub stalled_on: Vec<Ty<'tcx>>,
+    pub stalled_on: Vec<ty::InferTy>,
 }
 
 // `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
@@ -263,8 +263,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
             // Match arms are in order of frequency, which matters because this
             // code is so hot. 1 and 0 dominate; 2+ is fairly rare.
             1 => {
-                let ty = pending_obligation.stalled_on[0];
-                ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(ty)
+                let infer = pending_obligation.stalled_on[0];
+                ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(infer)
             }
             0 => {
                 // In this case we haven't changed, but wish to make a change.
@@ -274,8 +274,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
                 // This `for` loop was once a call to `all()`, but this lower-level
                 // form was a perf win. See #64545 for details.
                 (|| {
-                    for &ty in &pending_obligation.stalled_on {
-                        if ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(ty) {
+                    for &infer in &pending_obligation.stalled_on {
+                        if ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(infer) {
                             return true;
                         }
                     }
@@ -305,6 +305,13 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
 
         debug!("process_obligation: obligation = {:?} cause = {:?}", obligation, obligation.cause);
 
+        fn infer_ty(ty: Ty<'tcx>) -> ty::InferTy {
+            match ty.kind {
+                ty::Infer(infer) => infer,
+                _ => panic!(),
+            }
+        }
+
         match obligation.predicate {
             ty::Predicate::Trait(ref data) => {
                 let trait_obligation = obligation.with(data.clone());
@@ -459,7 +466,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
                     obligation.cause.span,
                 ) {
                     None => {
-                        pending_obligation.stalled_on = vec![ty];
+                        pending_obligation.stalled_on = vec![infer_ty(ty)];
                         ProcessResult::Unchanged
                     }
                     Some(os) => ProcessResult::Changed(mk_pending(os))
@@ -472,8 +479,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
                                                            subtype) {
                     None => {
                         // None means that both are unresolved.
-                        pending_obligation.stalled_on = vec![subtype.skip_binder().a,
-                                                             subtype.skip_binder().b];
+                        pending_obligation.stalled_on = vec![infer_ty(subtype.skip_binder().a),
+                                                             infer_ty(subtype.skip_binder().b)];
                         ProcessResult::Unchanged
                     }
                     Some(Ok(ok)) => {
@@ -517,7 +524,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
                             ))
                         }
                     } else {
-                        pending_obligation.stalled_on = substs.types().collect();
+                        pending_obligation.stalled_on =
+                            substs.types().map(|ty| infer_ty(ty)).collect();
                         ProcessResult::Unchanged
                     }
                 }
@@ -542,13 +550,13 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
 fn trait_ref_type_vars<'a, 'tcx>(
     selcx: &mut SelectionContext<'a, 'tcx>,
     t: ty::PolyTraitRef<'tcx>,
-) -> Vec<Ty<'tcx>> {
+) -> Vec<ty::InferTy> {
     t.skip_binder() // ok b/c this check doesn't care about regions
      .input_types()
      .map(|t| selcx.infcx().resolve_vars_if_possible(&t))
      .filter(|t| t.has_infer_types())
      .flat_map(|t| t.walk())
-     .filter(|t| match t.kind { ty::Infer(_) => true, _ => false })
+     .filter_map(|t| match t.kind { ty::Infer(infer) => Some(infer), _ => None })
      .collect()
 }