diff options
| -rw-r--r-- | src/librustc/traits/mod.rs | 8 | ||||
| -rw-r--r-- | src/librustc/traits/select.rs | 11 | ||||
| -rw-r--r-- | src/librustc/ty/mod.rs | 2 |
3 files changed, 14 insertions, 7 deletions
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 7f232b310c0..2bc396eb04e 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -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 type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>; 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 @@ impl<'tcx> ObligationCause<'tcx> { } } -#[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 diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 4ed25646d43..90162c3deca 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -53,7 +53,7 @@ use std::rc::Rc; 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 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // 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 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { 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) } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 14d33b0729a..3ab2cd274b9 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1504,7 +1504,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for AdtDef { } } -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub enum AdtKind { Struct, Union, Enum } bitflags! { |
