Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to EarlyBinder for explicit_item_bounds #110556

Merged
merged 4 commits into from
Apr 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
.copied()
.find_map(find_fn_kind_from_did),
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => tcx
.bound_explicit_item_bounds(def_id)
.explicit_item_bounds(def_id)
.subst_iter_copied(tcx, substs)
.find_map(find_fn_kind_from_did),
ty::Closure(_, substs) => match substs.as_closure().kind() {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
};
let prohibit_opaque = tcx
.explicit_item_bounds(def_id)
.iter()
.subst_identity_iter_copied()
.try_for_each(|(predicate, _)| predicate.visit_with(&mut visitor));

if let Some(ty) = prohibit_opaque.break_value() {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -839,7 +839,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
});
self.types.insert(proj.def_id, (infer_ty, proj.substs));
// Recurse into bounds
for (pred, pred_span) in self.interner().bound_explicit_item_bounds(proj.def_id).subst_iter_copied(self.interner(), proj.substs) {
for (pred, pred_span) in self.interner().explicit_item_bounds(proj.def_id).subst_iter_copied(self.interner(), proj.substs) {
let pred = pred.fold_with(self);
let pred = self.ocx.normalize(
&ObligationCause::misc(self.span, self.body_id),
Expand Down Expand Up @@ -2023,7 +2023,7 @@ pub(super) fn check_type_bounds<'tcx>(
};

let obligations: Vec<_> = tcx
.bound_explicit_item_bounds(trait_ty.def_id)
.explicit_item_bounds(trait_ty.def_id)
.subst_iter_copied(tcx, rebased_substs)
.map(|(concrete_ty_bound, span)| {
debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,9 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
tcx,
param_env,
item_def_id,
tcx.explicit_item_bounds(item_def_id).to_vec(),
tcx.explicit_item_bounds(item_def_id)
.subst_identity_iter_copied()
.collect::<Vec<_>>(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the turbofish necessary here? Alternatively, you could do something like subst_identity().to_vec(), right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This maybe ties into a larger question (sorry for the long comment below):

Right now, EarlyBinder<T>::subst_identity has the bound T: TypeFoldable, so it's not actually available here. I was considering getting rid of the TypeFoldable bound but wasn't sure how important it is to how EarlyBinder should work -- i.e., right now you can only call subst_identity on things that you could also call subst on. (Maybe this property would come in handy in the future if doing larger refactorings?)

The lack of subst_identity is what motivated me to add subst_identity_iter_copied in this PR, as an identity version of subst_iter_copied.

Haha but now I'm worried that I'm overthinking and over-complicating this. If it's alright to do subst_identity on any inner type, then we don't have to add new methods on EarlyBinder in this PR, and every subst_identity_iter_copied would just become subst_identity().iter() (or in the case above, subst_identity().to_vec() as you mentioned). What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmmmmmm.. maybe we could implement subst_identity on anything that implements TypeVisitable? We probably don't need it to be TypeFoldable, but I could potentially see us using some folder to make sure that it's actually valid to subst identity?

&FxIndexSet::default(),
gat_def_id.def_id,
gat_generics,
Expand Down Expand Up @@ -1125,7 +1127,7 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt
let bounds = wfcx.tcx().explicit_item_bounds(item.def_id);

debug!("check_associated_type_bounds: bounds={:?}", bounds);
let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
let wf_obligations = bounds.subst_identity_iter_copied().flat_map(|(bound, bound_span)| {
let normalized_bound = wfcx.normalize(span, None, bound);
traits::wf::predicate_obligations(
wfcx.infcx,
Expand Down Expand Up @@ -1588,7 +1590,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
}
});
for (bound, bound_span) in tcx
.bound_explicit_item_bounds(opaque_ty.def_id)
.explicit_item_bounds(opaque_ty.def_id)
.subst_iter_copied(tcx, opaque_ty.substs)
{
let bound = self.wfcx.normalize(bound_span, None, bound);
Expand Down
22 changes: 12 additions & 10 deletions compiler/rustc_hir_analysis/src/collect/item_bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,14 @@ fn opaque_type_bounds<'tcx>(
pub(super) fn explicit_item_bounds(
tcx: TyCtxt<'_>,
def_id: LocalDefId,
) -> &'_ [(ty::Predicate<'_>, Span)] {
) -> ty::EarlyBinder<&'_ [(ty::Predicate<'_>, Span)]> {
match tcx.opt_rpitit_info(def_id.to_def_id()) {
// RPITIT's bounds are the same as opaque type bounds, but with
// a projection self type.
Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
let item = tcx.hir().get_by_def_id(opaque_def_id.expect_local()).expect_item();
let opaque_ty = item.expect_opaque_ty();
return opaque_type_bounds(
return ty::EarlyBinder(opaque_type_bounds(
tcx,
opaque_def_id.expect_local(),
opaque_ty.bounds,
Expand All @@ -95,15 +95,15 @@ pub(super) fn explicit_item_bounds(
ty::InternalSubsts::identity_for_item(tcx, def_id),
),
item.span,
);
));
}
// These should have been fed!
Some(ty::ImplTraitInTraitData::Impl { .. }) => unreachable!(),
None => {}
}

let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
match tcx.hir().get(hir_id) {
let bounds = match tcx.hir().get(hir_id) {
hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Type(bounds, _),
span,
Expand All @@ -123,16 +123,18 @@ pub(super) fn explicit_item_bounds(
opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
}
_ => bug!("item_bounds called on {:?}", def_id),
}
};
ty::EarlyBinder(bounds)
}

pub(super) fn item_bounds(
tcx: TyCtxt<'_>,
def_id: DefId,
) -> ty::EarlyBinder<&'_ ty::List<ty::Predicate<'_>>> {
let bounds = tcx.mk_predicates_from_iter(util::elaborate(
tcx,
tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound),
));
ty::EarlyBinder(bounds)
tcx.explicit_item_bounds(def_id).map_bound(|bounds| {
tcx.mk_predicates_from_iter(util::elaborate(
tcx,
bounds.iter().map(|&(bound, _span)| bound),
))
})
}
3 changes: 1 addition & 2 deletions compiler/rustc_hir_analysis/src/variance/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
let mut collector =
OpaqueTypeLifetimeCollector { tcx, root_def_id: item_def_id.to_def_id(), variances };
let id_substs = ty::InternalSubsts::identity_for_item(tcx, item_def_id);
for pred in tcx.bound_explicit_item_bounds(item_def_id.to_def_id()).transpose_iter() {
let pred = pred.map_bound(|(pred, _)| *pred).subst(tcx, id_substs);
for (pred, _) in tcx.explicit_item_bounds(item_def_id).subst_iter_copied(tcx, id_substs) {
debug!(?pred);

// We only ignore opaque type substs if the opaque type is the outermost type.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
for ty in [first_ty, second_ty] {
for (pred, _) in self
.tcx
.bound_explicit_item_bounds(rpit_def_id)
.explicit_item_bounds(rpit_def_id)
.subst_iter_copied(self.tcx, substs)
{
let pred = pred.kind().rebind(match pred.kind().skip_binder() {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_typeck/src/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self
.deduce_closure_signature_from_predicates(
expected_ty,
self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs),
self.tcx.explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs),
),
ty::Dynamic(ref object_type, ..) => {
let sig = object_type.projection_bounds().find_map(|pb| {
Expand Down Expand Up @@ -713,13 +713,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self
.tcx
.bound_explicit_item_bounds(def_id)
.explicit_item_bounds(def_id)
.subst_iter_copied(self.tcx, substs)
.find_map(|(p, s)| get_future_output(p, s))?,
ty::Error(_) => return None,
ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => self
.tcx
.bound_explicit_item_bounds(proj.def_id)
.explicit_item_bounds(proj.def_id)
.subst_iter_copied(self.tcx, proj.substs)
.find_map(|(p, s)| get_future_output(p, s))?,
_ => span_bug!(
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/generator_interior/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ fn check_must_not_suspend_ty<'tcx>(
// FIXME: support adding the attribute to TAITs
ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
let mut has_emitted = false;
for &(predicate, _) in fcx.tcx.explicit_item_bounds(def) {
for &(predicate, _) in fcx.tcx.explicit_item_bounds(def).skip_binder() {
// We only look at the `DefId`, so it is safe to skip the binder here.
if let ty::PredicateKind::Clause(ty::Clause::Trait(ref poly_trait_predicate)) =
predicate.kind().skip_binder()
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ impl<'tcx> InferCtxt<'tcx> {
let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];

self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs).find_map(
self.tcx.explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs).find_map(
|(predicate, _)| {
predicate
.kind()
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ impl<'tcx> InferCtxt<'tcx> {
.obligations;
}

let item_bounds = tcx.bound_explicit_item_bounds(def_id.to_def_id());
let item_bounds = tcx.explicit_item_bounds(def_id);

for (predicate, _) in item_bounds.subst_iter_copied(tcx, substs) {
let predicate = predicate.fold_with(&mut BottomUpFolder {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
// For every projection predicate in the opaque type's explicit bounds,
// check that the type that we're assigning actually satisfies the bounds
// of the associated type.
for &(pred, pred_span) in cx.tcx.explicit_item_bounds(def_id) {
for (pred, pred_span) in cx.tcx.explicit_item_bounds(def_id).subst_identity_iter_copied() {
// Liberate bound regions in the predicate since we
// don't actually care about lifetimes in this check.
let predicate = cx.tcx.liberate_late_bound_regions(def_id, pred.kind());
Expand Down Expand Up @@ -112,7 +112,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
// with `impl Send: OtherTrait`.
for (assoc_pred, assoc_pred_span) in cx
.tcx
.bound_explicit_item_bounds(proj.projection_ty.def_id)
.explicit_item_bounds(proj.projection_ty.def_id)
.subst_iter_copied(cx.tcx, &proj.projection_ty.substs)
{
let assoc_pred = assoc_pred.fold_with(proj_replacer);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
}
ty::Adt(def, _) => is_def_must_use(cx, def.did(), span),
ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
elaborate(cx.tcx, cx.tcx.explicit_item_bounds(def).iter().cloned())
elaborate(cx.tcx, cx.tcx.explicit_item_bounds(def).subst_identity_iter_copied())
// We only care about self bounds for the impl-trait
.filter_only_self()
.find_map(|(pred, _span)| {
Expand Down
16 changes: 15 additions & 1 deletion compiler/rustc_metadata/src/rmeta/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
use rustc_middle::ty::codec::TyDecoder;
use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::GeneratorDiagnosticData;
use rustc_middle::ty::{self, ParameterizedOverTcx, Ty, TyCtxt, Visibility};
use rustc_middle::ty::{self, ParameterizedOverTcx, Predicate, Ty, TyCtxt, Visibility};
use rustc_serialize::opaque::MemDecoder;
use rustc_serialize::{Decodable, Decoder};
use rustc_session::cstore::{
Expand Down Expand Up @@ -857,6 +857,20 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
)
}

fn get_explicit_item_bounds(
self,
index: DefIndex,
tcx: TyCtxt<'tcx>,
) -> ty::EarlyBinder<&'tcx [(Predicate<'tcx>, Span)]> {
let lazy = self.root.tables.explicit_item_bounds.get(self, index);
let output = if lazy.is_default() {
&mut []
} else {
tcx.arena.alloc_from_iter(lazy.decode((self, tcx)))
};
ty::EarlyBinder(&*output)
}

fn get_variant(self, kind: &DefKind, index: DefIndex, parent_did: DefId) -> ty::VariantDef {
let adt_kind = match kind {
DefKind::Variant => ty::AdtKind::Enum,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ impl IntoArgs for (CrateNum, SimplifiedType) {
}

provide! { tcx, def_id, other, cdata,
explicit_item_bounds => { table_defaulted_array }
explicit_item_bounds => { cdata.get_explicit_item_bounds(def_id.index, tcx) }
explicit_predicates_of => { table }
generics_of => { table }
inferred_outlives_of => { table_defaulted_array }
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1425,7 +1425,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {

fn encode_explicit_item_bounds(&mut self, def_id: DefId) {
debug!("EncodeContext::encode_explicit_item_bounds({:?})", def_id);
let bounds = self.tcx.explicit_item_bounds(def_id);
let bounds = self.tcx.explicit_item_bounds(def_id).skip_binder();
record_defaulted_array!(self.tables.explicit_item_bounds[def_id] <- bounds);
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ rustc_queries! {
/// `key` is the `DefId` of the associated type or opaque type.
///
/// Bounds from the parent (e.g. with nested impl trait) are not included.
query explicit_item_bounds(key: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx [(ty::Predicate<'tcx>, Span)]> {
desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
separate_provide_extern
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1611,7 +1611,7 @@ impl<'tcx> TyCtxt<'tcx> {
let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() else { return false };
let future_trait = self.require_lang_item(LangItem::Future, None);

self.explicit_item_bounds(def_id).iter().any(|(predicate, _)| {
self.explicit_item_bounds(def_id).skip_binder().iter().any(|&(predicate, _)| {
let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() else {
return false;
};
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,7 @@ pub trait PrettyPrinter<'tcx>:

// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
// by looking up the projections associated with the def_id.
let bounds = tcx.bound_explicit_item_bounds(def_id);
let bounds = tcx.explicit_item_bounds(def_id);

let mut traits = FxIndexMap::default();
let mut fn_traits = FxIndexMap::default();
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_middle/src/ty/subst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,12 @@ where
) -> SubstIter<'s, 'tcx, I> {
SubstIter { it: self.0.into_iter(), tcx, substs }
}

/// Similar to [`subst_identity`](EarlyBinder::subst_identity),
/// but on an iterator of `TypeFoldable` values.
pub fn subst_identity_iter(self) -> I::IntoIter {
self.0.into_iter()
}
}

pub struct SubstIter<'s, 'tcx, I: IntoIterator> {
Expand Down Expand Up @@ -677,6 +683,12 @@ where
) -> SubstIterCopied<'s, 'tcx, I> {
SubstIterCopied { it: self.0.into_iter(), tcx, substs }
}

/// Similar to [`subst_identity`](EarlyBinder::subst_identity),
/// but on an iterator of values that deref to a `TypeFoldable`.
pub fn subst_identity_iter_copied(self) -> impl Iterator<Item = <I::Item as Deref>::Target> {
self.0.into_iter().map(|v| *v)
}
}

pub struct SubstIterCopied<'a, 'tcx, I: IntoIterator> {
Expand Down
7 changes: 0 additions & 7 deletions compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -694,13 +694,6 @@ impl<'tcx> TyCtxt<'tcx> {
if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) }
}

pub fn bound_explicit_item_bounds(
self,
def_id: DefId,
) -> ty::EarlyBinder<&'tcx [(ty::Predicate<'tcx>, rustc_span::Span)]> {
ty::EarlyBinder(self.explicit_item_bounds(def_id))
}

/// Returns names of captured upvars for closures and generators.
///
/// Here are some examples:
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1800,7 +1800,7 @@ fn check_must_not_suspend_ty<'tcx>(
// FIXME: support adding the attribute to TAITs
ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
let mut has_emitted = false;
for &(predicate, _) in tcx.explicit_item_bounds(def) {
for &(predicate, _) in tcx.explicit_item_bounds(def).skip_binder() {
// We only look at the `DefId`, so it is safe to skip the binder here.
if let ty::PredicateKind::Clause(ty::Clause::Trait(ref poly_trait_predicate)) =
predicate.kind().skip_binder()
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_privacy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ where
// and are visited by shallow visitors.
self.visit_predicates(ty::GenericPredicates {
parent: None,
predicates: tcx.explicit_item_bounds(def_id),
predicates: tcx.explicit_item_bounds(def_id).skip_binder(),
})?;
}
}
Expand Down Expand Up @@ -1784,7 +1784,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
fn bounds(&mut self) -> &mut Self {
self.visit_predicates(ty::GenericPredicates {
parent: None,
predicates: self.tcx.explicit_item_bounds(self.item_def_id),
predicates: self.tcx.explicit_item_bounds(self.item_def_id).skip_binder(),
});
self
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_trait_selection/src/traits/object_safety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,8 @@ fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span
tcx.associated_items(trait_def_id)
.in_definition_order()
.filter(|item| item.kind == ty::AssocKind::Type)
.flat_map(|item| tcx.explicit_item_bounds(item.def_id))
.filter_map(|pred_span| predicate_references_self(tcx, *pred_span))
.flat_map(|item| tcx.explicit_item_bounds(item.def_id).subst_identity_iter_copied())
.filter_map(|pred_span| predicate_references_self(tcx, pred_span))
.collect()
}

Expand Down
Loading