diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index c1f0a6e9834..c07ff516579 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -116,11 +116,11 @@ pub fn elaborate_predicates_with_span<'tcx>( pub fn elaborate_obligations<'tcx>( tcx: TyCtxt<'tcx>, - mut obligations: Vec>, + obligations: Vec>, ) -> Elaborator<'tcx> { - let mut visited = PredicateSet::new(tcx); - obligations.retain(|obligation| visited.insert(obligation.predicate)); - Elaborator { stack: obligations, visited } + let mut elaborator = Elaborator { stack: Vec::new(), visited: PredicateSet::new(tcx) }; + elaborator.extend_deduped(obligations); + elaborator } fn predicate_obligation<'tcx>( @@ -132,6 +132,15 @@ fn predicate_obligation<'tcx>( } impl<'tcx> Elaborator<'tcx> { + fn extend_deduped(&mut self, obligations: impl IntoIterator>) { + // Only keep those bounds that we haven't already seen. + // This is necessary to prevent infinite recursion in some + // cases. One common case is when people define + // `trait Sized: Sized { }` rather than `trait Sized { }`. + // let visited = &mut self.visited; + self.stack.extend(obligations.into_iter().filter(|o| self.visited.insert(o.predicate))); + } + pub fn filter_to_traits(self) -> FilterToTraits { FilterToTraits::new(self) } @@ -172,15 +181,7 @@ fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) { ) }); debug!(?data, ?obligations, "super_predicates"); - - // Only keep those bounds that we haven't already seen. - // This is necessary to prevent infinite recursion in some - // cases. One common case is when people define - // `trait Sized: Sized { }` rather than `trait Sized { }`. - let visited = &mut self.visited; - let obligations = obligations.filter(|o| visited.insert(o.predicate)); - - self.stack.extend(obligations); + self.extend_deduped(obligations); } ty::PredicateKind::WellFormed(..) => { // Currently, we do not elaborate WF predicates, @@ -237,10 +238,9 @@ fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) { return; } - let visited = &mut self.visited; let mut components = smallvec![]; push_outlives_components(tcx, ty_max, &mut components); - self.stack.extend( + self.extend_deduped( components .into_iter() .filter_map(|component| match component { @@ -280,7 +280,6 @@ fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) { .map(|predicate_kind| { bound_predicate.rebind(predicate_kind).to_predicate(tcx) }) - .filter(|&predicate| visited.insert(predicate)) .map(|predicate| { predicate_obligation( predicate,