Skip to content

Commit 61c1894

Browse files
Simplify transitive_bounds_that_define_assoc_item
1 parent 09df610 commit 61c1894

File tree

1 file changed

+28
-33
lines changed
  • compiler/rustc_infer/src/traits

1 file changed

+28
-33
lines changed

compiler/rustc_infer/src/traits/util.rs

+28-33
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use smallvec::smallvec;
22

33
use crate::infer::outlives::components::{push_outlives_components, Component};
44
use crate::traits::{self, Obligation, PredicateObligation};
5-
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
5+
use rustc_data_structures::fx::FxHashSet;
66
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
77
use rustc_span::symbol::Ident;
88
use rustc_span::Span;
@@ -76,7 +76,13 @@ impl<'tcx> Extend<ty::Predicate<'tcx>> for PredicateSet<'tcx> {
7676
pub struct Elaborator<'tcx, O> {
7777
stack: Vec<O>,
7878
visited: PredicateSet<'tcx>,
79-
only_self: bool,
79+
mode: Filter,
80+
}
81+
82+
enum Filter {
83+
All,
84+
OnlySelf,
85+
OnlySelfThatDefines(Ident),
8086
}
8187

8288
/// Describes how to elaborate an obligation into a sub-obligation.
@@ -224,7 +230,7 @@ pub fn elaborate<'tcx, O: Elaboratable<'tcx>>(
224230
obligations: impl IntoIterator<Item = O>,
225231
) -> Elaborator<'tcx, O> {
226232
let mut elaborator =
227-
Elaborator { stack: Vec::new(), visited: PredicateSet::new(tcx), only_self: false };
233+
Elaborator { stack: Vec::new(), visited: PredicateSet::new(tcx), mode: Filter::All };
228234
elaborator.extend_deduped(obligations);
229235
elaborator
230236
}
@@ -242,7 +248,13 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
242248
/// Filter to only the supertraits of trait predicates, i.e. only the predicates
243249
/// that have `Self` as their self type, instead of all implied predicates.
244250
pub fn filter_only_self(mut self) -> Self {
245-
self.only_self = true;
251+
self.mode = Filter::OnlySelf;
252+
self
253+
}
254+
255+
/// Filter to only the supertraits of trait predicates that define the assoc_ty.
256+
pub fn filter_only_self_that_defines(mut self, assoc_ty: Ident) -> Self {
257+
self.mode = Filter::OnlySelfThatDefines(assoc_ty);
246258
self
247259
}
248260

@@ -257,10 +269,12 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
257269
return;
258270
}
259271
// Get predicates implied by the trait, or only super predicates if we only care about self predicates.
260-
let predicates = if self.only_self {
261-
tcx.super_predicates_of(data.def_id())
262-
} else {
263-
tcx.implied_predicates_of(data.def_id())
272+
let predicates = match self.mode {
273+
Filter::All => tcx.implied_predicates_of(data.def_id()),
274+
Filter::OnlySelf => tcx.super_predicates_of(data.def_id()),
275+
Filter::OnlySelfThatDefines(ident) => {
276+
tcx.super_predicates_that_define_assoc_item((data.def_id(), ident))
277+
}
264278
};
265279

266280
let obligations =
@@ -416,7 +430,7 @@ pub fn supertraits<'tcx>(
416430
pub fn transitive_bounds<'tcx>(
417431
tcx: TyCtxt<'tcx>,
418432
trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
419-
) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> {
433+
) -> FilterToTraits<Elaborator<'tcx, ty::Predicate<'tcx>>> {
420434
elaborate(tcx, trait_refs.map(|trait_ref| trait_ref.to_predicate(tcx)))
421435
.filter_only_self()
422436
.filter_to_traits()
@@ -429,31 +443,12 @@ pub fn transitive_bounds<'tcx>(
429443
/// `T::Item` and helps to avoid cycle errors (see e.g. #35237).
430444
pub fn transitive_bounds_that_define_assoc_item<'tcx>(
431445
tcx: TyCtxt<'tcx>,
432-
bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
446+
trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
433447
assoc_name: Ident,
434-
) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> {
435-
let mut stack: Vec<_> = bounds.collect();
436-
let mut visited = FxIndexSet::default();
437-
438-
std::iter::from_fn(move || {
439-
while let Some(trait_ref) = stack.pop() {
440-
let anon_trait_ref = tcx.anonymize_bound_vars(trait_ref);
441-
if visited.insert(anon_trait_ref) {
442-
let super_predicates =
443-
tcx.super_predicates_that_define_assoc_item((trait_ref.def_id(), assoc_name));
444-
for (super_predicate, _) in super_predicates.predicates {
445-
let subst_predicate = super_predicate.subst_supertrait(tcx, &trait_ref);
446-
if let Some(binder) = subst_predicate.as_trait_clause() {
447-
stack.push(binder.map_bound(|t| t.trait_ref));
448-
}
449-
}
450-
451-
return Some(trait_ref);
452-
}
453-
}
454-
455-
return None;
456-
})
448+
) -> FilterToTraits<Elaborator<'tcx, ty::Predicate<'tcx>>> {
449+
elaborate(tcx, trait_refs.map(|trait_ref| trait_ref.to_predicate(tcx)))
450+
.filter_only_self_that_defines(assoc_name)
451+
.filter_to_traits()
457452
}
458453

459454
///////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)