summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_infer/src/traits/util.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_infer/src/traits/util.rs')
-rw-r--r--compiler/rustc_infer/src/traits/util.rs87
1 files changed, 47 insertions, 40 deletions
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index cd5bde2a7..c07ff5165 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<PredicateObligation<'tcx>>,
+ obligations: Vec<PredicateObligation<'tcx>>,
) -> 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<Item = PredicateObligation<'tcx>>) {
+ // 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<Self> {
FilterToTraits::new(self)
}
@@ -145,40 +154,34 @@ impl<'tcx> Elaborator<'tcx> {
// Get predicates declared on the trait.
let predicates = tcx.super_predicates_of(data.def_id());
- let obligations = predicates.predicates.iter().map(|&(mut pred, span)| {
- // when parent predicate is non-const, elaborate it to non-const predicates.
- if data.constness == ty::BoundConstness::NotConst {
- pred = pred.without_const(tcx);
- }
-
- let cause = obligation.cause.clone().derived_cause(
- bound_predicate.rebind(data),
- |derived| {
- traits::ImplDerivedObligation(Box::new(
- traits::ImplDerivedObligationCause {
- derived,
- impl_def_id: data.def_id(),
- span,
- },
- ))
- },
- );
- predicate_obligation(
- pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)),
- obligation.param_env,
- cause,
- )
- });
+ let obligations =
+ predicates.predicates.iter().enumerate().map(|(index, &(mut pred, span))| {
+ // when parent predicate is non-const, elaborate it to non-const predicates.
+ if data.constness == ty::BoundConstness::NotConst {
+ pred = pred.without_const(tcx);
+ }
+
+ let cause = obligation.cause.clone().derived_cause(
+ bound_predicate.rebind(data),
+ |derived| {
+ traits::ImplDerivedObligation(Box::new(
+ traits::ImplDerivedObligationCause {
+ derived,
+ impl_or_alias_def_id: data.def_id(),
+ impl_def_predicate_index: Some(index),
+ span,
+ },
+ ))
+ },
+ );
+ predicate_obligation(
+ pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)),
+ obligation.param_env,
+ cause,
+ )
+ });
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,
@@ -235,10 +238,9 @@ impl<'tcx> Elaborator<'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 {
@@ -278,7 +280,6 @@ impl<'tcx> Elaborator<'tcx> {
.map(|predicate_kind| {
bound_predicate.rebind(predicate_kind).to_predicate(tcx)
})
- .filter(|&predicate| visited.insert(predicate))
.map(|predicate| {
predicate_obligation(
predicate,
@@ -292,6 +293,12 @@ impl<'tcx> Elaborator<'tcx> {
// Nothing to elaborate
}
ty::PredicateKind::Ambiguous => {}
+ ty::PredicateKind::AliasEq(..) => {
+ // No
+ }
+ ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => {
+ // Nothing to elaborate
+ }
}
}
}