about summary refs log tree commit diff
diff options
context:
space:
mode:
authorlcnr <rust@lcnr.de>2022-05-24 09:22:24 +0200
committerlcnr <rust@lcnr.de>2022-05-25 07:40:38 +0200
commitbff7b5130d49da7c86d688843292c10b82a4e6a0 (patch)
treed87c08d76572f005112a6fa98cccca2ff09aeaa5
parenta76277c6c4cd7f175efd2d86477447bd6577aea2 (diff)
downloadrust-bff7b5130d49da7c86d688843292c10b82a4e6a0.tar.gz
rust-bff7b5130d49da7c86d688843292c10b82a4e6a0.zip
move fast reject test out of `SelectionContext::match_impl`.
`match_impl` has two call sites. For one of them (within `rematch_impl`)
the fast reject test isn't necessary, because any rejection would
represent a compiler bug.

This commit moves the fast reject test to the other `match_impl` call
site, in `assemble_candidates_from_impls`. This lets us move the fast
reject test outside the `probe` call in that function. This avoids the
taking of useless snapshots when the fast reject test succeeds, which
gives a performance win when compiling the `bitmaps` and `nalgebra`
crates.

Co-authored-by: name <n.nethercote@gmail.com>
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs13
2 files changed, 12 insertions, 11 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 07720ba71ca..c8b4303e1e0 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -539,8 +539,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             obligation.predicate.def_id(),
             obligation.predicate.skip_binder().trait_ref.self_ty(),
             |impl_def_id| {
+                // Before we create the substitutions and everything, first
+                // consider a "quick reject". This avoids creating more types
+                // and so forth that we need to.
+                let impl_trait_ref = self.tcx().bound_impl_trait_ref(impl_def_id).unwrap();
+                if self.fast_reject_trait_refs(obligation, &impl_trait_ref.0) {
+                    return;
+                }
+
                 self.infcx.probe(|_| {
-                    if let Ok(_substs) = self.match_impl(impl_def_id, obligation) {
+                    if let Ok(_substs) = self.match_impl(impl_def_id, impl_trait_ref, obligation) {
                         candidates.vec.push(ImplCandidate(impl_def_id));
                     }
                 });
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 25b19c02a59..c7ebc194ea5 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2043,7 +2043,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         impl_def_id: DefId,
         obligation: &TraitObligation<'tcx>,
     ) -> Normalized<'tcx, SubstsRef<'tcx>> {
-        match self.match_impl(impl_def_id, obligation) {
+        let impl_trait_ref = self.tcx().bound_impl_trait_ref(impl_def_id).unwrap();
+        match self.match_impl(impl_def_id, impl_trait_ref, obligation) {
             Ok(substs) => substs,
             Err(()) => {
                 self.infcx.tcx.sess.delay_span_bug(
@@ -2070,17 +2071,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     fn match_impl(
         &mut self,
         impl_def_id: DefId,
+        impl_trait_ref: EarlyBinder<ty::TraitRef<'tcx>>,
         obligation: &TraitObligation<'tcx>,
     ) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> {
-        let impl_trait_ref = self.tcx().bound_impl_trait_ref(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.0) {
-            return Err(());
-        }
-
         let placeholder_obligation =
             self.infcx().replace_bound_vars_with_placeholders(obligation.predicate);
         let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref;