about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume.gomez@huawei.com>2022-03-26 14:58:19 +0100
committerGuillaume Gomez <guillaume.gomez@huawei.com>2022-03-26 14:58:19 +0100
commitad887322541b1c255b210cf87fae675072d1027f (patch)
treebd876f2d03dee317945b74bed25d539f39848af0
parent3fe3b89cd57229343eeca753fdd8c63d9b03c65c (diff)
downloadrust-ad887322541b1c255b210cf87fae675072d1027f.tar.gz
rust-ad887322541b1c255b210cf87fae675072d1027f.zip
Fix perf issue for auto trait selection
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs4
3 files changed, 29 insertions, 2 deletions
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 93ece753728..dc16460ca43 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -999,6 +999,15 @@ impl<'tcx> PolyTraitRef<'tcx> {
             polarity: ty::ImplPolarity::Positive,
         })
     }
+
+    /// Same as [`PolyTraitRef::to_poly_trait_predicate`] but sets a negative polarity instead.
+    pub fn to_poly_trait_predicate_negative_polarity(&self) -> ty::PolyTraitPredicate<'tcx> {
+        self.map_bound(|trait_ref| ty::TraitPredicate {
+            trait_ref,
+            constness: ty::BoundConstness::NotConst,
+            polarity: ty::ImplPolarity::Negative,
+        })
+    }
 }
 
 /// An existential reference to a trait, where `Self` is erased.
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index c9398d746d7..6f6f21aa788 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -101,6 +101,24 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                          manual impl found, bailing out",
                         trait_ref
                     );
+                    return true;
+                }
+                _ => {}
+            }
+
+            let result = selcx.select(&Obligation::new(
+                ObligationCause::dummy(),
+                orig_env,
+                trait_pred.to_poly_trait_predicate_negative_polarity(),
+            ));
+
+            match result {
+                Ok(Some(ImplSource::UserDefined(_))) => {
+                    debug!(
+                        "find_auto_trait_generics({:?}): \
+                         manual impl found, bailing out",
+                        trait_ref
+                    );
                     true
                 }
                 _ => false,
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 6d232d86d8a..4704d841012 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1272,7 +1272,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // the master cache. Since coherence executes pretty quickly,
         // it's not worth going to more trouble to increase the
         // hit-rate, I don't think.
-        if self.intercrate || self.allow_negative_impls {
+        if self.intercrate {
             return false;
         }
 
@@ -1289,7 +1289,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // mode, so don't do any caching. In particular, we might
         // re-use the same `InferCtxt` with both an intercrate
         // and non-intercrate `SelectionContext`
-        if self.intercrate || self.allow_negative_impls {
+        if self.intercrate {
             return None;
         }
         let tcx = self.tcx();