about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2014-11-16 07:10:37 -0500
committerNiko Matsakis <niko@alum.mit.edu>2014-11-17 14:25:11 -0500
commitd7bb01eb52d6b3b40084450d99eb928d74d25d6e (patch)
treed6191611ad5b572f9a4185b1d09a00e901135419
parentd93921b348f37d10850c5f9b077300158a623e35 (diff)
Use the quick reject mechanism during trait matching as well. Seems to
yield an incremental improvement (type-checking rustc drops from ~9s
to ~8s).
-rw-r--r--src/librustc/middle/traits/select.rs36
1 files changed, 34 insertions, 2 deletions
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index 7ea58be3480..3dbb7307dd6 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -27,6 +27,7 @@ use super::{VtableBuiltin, VtableImpl, VtableParam, VtableUnboxedClosure};
 use super::{VtableImplData, VtableParamData, VtableBuiltinData};
 use super::{util};
 
+use middle::fast_reject;
 use middle::mem_categorization::Typer;
 use middle::subst::{Subst, Substs, VecPerParamSpace};
 use middle::ty;
@@ -1767,12 +1768,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                   obligation: &Obligation)
                   -> Result<Substs, ()>
     {
+        let impl_trait_ref = ty::impl_trait_ref(self.tcx(),
+                                                impl_def_id).unwrap();
+
+        // Before we create the substitutions and everything, first
+        // consider a "quick reject". This avoids creating more types
+        // and so forth that we need to.
+        if self.fast_reject_trait_refs(obligation, &*impl_trait_ref) {
+            return Err(());
+        }
+
         let impl_substs = util::fresh_substs_for_impl(self.infcx,
                                                       obligation.cause.span,
                                                       impl_def_id);
 
-        let impl_trait_ref = ty::impl_trait_ref(self.tcx(),
-                                                impl_def_id).unwrap();
         let impl_trait_ref = impl_trait_ref.subst(self.tcx(),
                                                   &impl_substs);
 
@@ -1782,6 +1791,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
     }
 
+    fn fast_reject_trait_refs(&mut self,
+                              obligation: &Obligation,
+                              impl_trait_ref: &ty::TraitRef)
+                              -> bool
+    {
+        // We can avoid creating type variables and doing the full
+        // substitution if we find that any of the input types, when
+        // simplified, do not match.
+
+        obligation.trait_ref.input_types().iter()
+            .zip(impl_trait_ref.input_types().iter())
+            .any(|(&obligation_ty, &impl_ty)| {
+                let simplified_obligation_ty =
+                    fast_reject::simplify_type(self.tcx(), obligation_ty, true);
+                let simplified_impl_ty =
+                    fast_reject::simplify_type(self.tcx(), impl_ty, false);
+
+                simplified_obligation_ty.is_some() &&
+                    simplified_impl_ty.is_some() &&
+                    simplified_obligation_ty != simplified_impl_ty
+            })
+    }
+
     fn match_trait_refs(&mut self,
                         obligation: &Obligation,
                         trait_ref: Rc<ty::TraitRef>)