]> git.lizzy.rs Git - rust.git/commitdiff
impl_or_trait_obligations: deduplicate obligations
authorTatsuyuki Ishi <ishitatsuyuki@gmail.com>
Sun, 18 Feb 2018 12:23:20 +0000 (21:23 +0900)
committerTatsuyuki Ishi <ishitatsuyuki@gmail.com>
Thu, 22 Feb 2018 09:40:49 +0000 (18:40 +0900)
src/librustc/traits/mod.rs
src/librustc/traits/select.rs
src/librustc/ty/mod.rs

index 7f232b310c0b388c351e1ad22f31f37799673719..2bc396eb04e750a704bdf7898b3350ec5580efe8 100644 (file)
@@ -73,7 +73,7 @@ pub enum IntercrateMode {
 /// either identifying an `impl` (e.g., `impl Eq for int`) that
 /// provides the required vtable, or else finding a bound that is in
 /// scope. The eventual result is usually a `Selection` (defined below).
-#[derive(Clone, PartialEq, Eq)]
+#[derive(Clone, PartialEq, Eq, Hash)]
 pub struct Obligation<'tcx, T> {
     pub cause: ObligationCause<'tcx>,
     pub param_env: ty::ParamEnv<'tcx>,
@@ -85,7 +85,7 @@ pub struct Obligation<'tcx, T> {
 pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;
 
 /// Why did we incur this obligation? Used for error reporting.
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
 pub struct ObligationCause<'tcx> {
     pub span: Span,
 
@@ -113,7 +113,7 @@ pub fn span<'a, 'gcx>(&self, tcx: &TyCtxt<'a, 'gcx, 'tcx>) -> Span {
     }
 }
 
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
 pub enum ObligationCauseCode<'tcx> {
     /// Not well classified or should be obvious from span.
     MiscObligation,
@@ -215,7 +215,7 @@ pub enum ObligationCauseCode<'tcx> {
     BlockTailExpression(ast::NodeId),
 }
 
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
 pub struct DerivedObligationCause<'tcx> {
     /// The trait reference of the parent obligation that led to the
     /// current obligation. Note that only trait obligations lead to
index 4ed25646d436d03671852d1d3a0fcd0f625e9c85..90162c3deca024e7fa14a80dfe75a929c49cf135 100644 (file)
@@ -53,7 +53,7 @@
 use syntax::abi::Abi;
 use hir;
 use lint;
-use util::nodemap::FxHashMap;
+use util::nodemap::{FxHashMap, FxHashSet};
 
 struct InferredObligationsSnapshotVecDelegate<'tcx> {
     phantom: PhantomData<&'tcx i32>,
@@ -3282,7 +3282,7 @@ fn impl_or_trait_obligations(&mut self,
         // that order.
         let predicates = tcx.predicates_of(def_id);
         assert_eq!(predicates.parent, None);
-        let predicates = predicates.predicates.iter().flat_map(|predicate| {
+        let mut predicates: Vec<_> = predicates.predicates.iter().flat_map(|predicate| {
             let predicate = normalize_with_depth(self, param_env, cause.clone(), recursion_depth,
                                                  &predicate.subst(tcx, substs));
             predicate.obligations.into_iter().chain(
@@ -3293,6 +3293,13 @@ fn impl_or_trait_obligations(&mut self,
                     predicate: predicate.value
                 }))
         }).collect();
+        // We are performing deduplication here to avoid exponential blowups
+        // (#38528) from happening, but the real cause of the duplication is
+        // unknown. What we know is that the deduplication avoids exponential
+        // amount of predicates being propogated when processing deeply nested
+        // types.
+        let mut seen = FxHashSet();
+        predicates.retain(|i| seen.insert(i.clone()));
         self.infcx().plug_leaks(skol_map, snapshot, predicates)
     }
 }
index 14d33b0729aae2707ec068a6251078bfc29e99eb..3ab2cd274b90ea98ad80a8d4998a9a0f6e00a6ec 100644 (file)
@@ -1504,7 +1504,7 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
 pub enum AdtKind { Struct, Union, Enum }
 
 bitflags! {