diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a5efcc989f6e4..10656c67f8b1f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2259,23 +2259,26 @@ fn clean_middle_opaque_bounds<'tcx>( let bindings: ThinVec<_> = bounds .iter() .filter_map(|bound| { - if let ty::ClauseKind::Projection(proj) = bound.kind().skip_binder() { - if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() { - Some(TypeBinding { - assoc: projection_to_path_segment( - bound.kind().rebind(proj.projection_ty), - cx, - ), - kind: TypeBindingKind::Equality { - term: clean_middle_term(bound.kind().rebind(proj.term), cx), - }, - }) - } else { - None - } - } else { - None + let ty::ClauseKind::Projection(proj) = bound.kind().skip_binder() else { + return None; + }; + if !simplify::trait_is_same_or_supertrait2( + cx, + trait_ref.skip_binder(), + proj.projection_ty.trait_ref(cx.tcx), + ) { + return None; } + + Some(TypeBinding { + assoc: projection_to_path_segment( + bound.kind().rebind(proj.projection_ty), + cx, + ), + kind: TypeBindingKind::Equality { + term: clean_middle_term(bound.kind().rebind(proj.term), cx), + }, + }) }) .collect(); diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 7b8f20326ed47..fbf1579e46208 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -72,6 +72,7 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec) -> ThinVec, bounds: &mut Vec, @@ -81,9 +82,8 @@ pub(crate) fn merge_bounds( rhs: &clean::Term, ) -> bool { !bounds.iter_mut().any(|b| { - let trait_ref = match *b { - clean::GenericBound::TraitBound(ref mut tr, _) => tr, - clean::GenericBound::Outlives(..) => return false, + let clean::GenericBound::TraitBound(trait_ref, _) = b else { + return false; }; // If this QPath's trait `trait_did` is the same as, or a supertrait // of, the bound's trait `did` then we can keep going, otherwise @@ -119,7 +119,12 @@ pub(crate) fn merge_bounds( }) } -fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId, trait_: DefId) -> bool { +// FIXME(fmease): @Task get rid of this! +pub(crate) fn trait_is_same_or_supertrait( + cx: &DocContext<'_>, + child: DefId, + trait_: DefId, +) -> bool { if child == trait_ { return true; } @@ -139,6 +144,33 @@ fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId, trait_: DefId) .any(|did| trait_is_same_or_supertrait(cx, did, trait_)) } +// @Task docs +pub(crate) fn trait_is_same_or_supertrait2<'tcx>( + cx: &DocContext<'tcx>, + child: ty::TraitRef<'tcx>, + trait_: ty::TraitRef<'tcx>, +) -> bool { + if child == trait_ { + return true; + } + let predicates = cx.tcx.super_predicates_of(child.def_id); + debug_assert!(cx.tcx.generics_of(child.def_id).has_self); + predicates + .predicates + .iter() + .filter_map(|(pred, _)| { + let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder() else { + return None; + }; + if pred.trait_ref.self_ty() != cx.tcx.types.self_param { + return None; + } + + Some(ty::EarlyBinder::bind(pred.trait_ref).instantiate(cx.tcx, child.args)) + }) + .any(|child| trait_is_same_or_supertrait2(cx, child, trait_)) +} + /// Move bounds that are (likely) directly attached to generic parameters from the where-clause to /// the respective parameter. ///