Change:
<!-- Thank you for finding a documentation problem! Documentation problems might be grammatical issues, typos, or unclear wording, please provide details regarding the documentation including where it is present. Note: If your issue is for one of these, please use their dedicated issue tracker instead: The Rust Book: Rust by Example: The Edition Guide: The Cargo Book: The Clippy Book: The Reference: The Rustonomicon: The Embedded Book: All other documentation issues should be filed here. Or, if you find an issue related to rustdoc (e.g. doctest, rustdoc UI), please use the bug report or blank issue template instead. -- The definition of the trait looks like: Rustdoc renders this as: This makes the trait bound for the associated type verbose and cryptic. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
label -A-docs C-bug T-rustdoc A-rustdoc-ui A-associated-items
I did a quick investigation: This reproduces on stable and nightly but only if the corresponding trait comes from an extern crate (which is the case with & ). Thus marking this issue as label A-cross-crate-reexports Minimal reproducer: claim
Highly related to / “duplicate” of although the latter is quite outdated.

Discussion:
} if let ty::TraitContainer = assoc_item.container { <ins> // FIXME(fmease): `tcx.explicit_item_bounds` does not contain the bounds of GATs, //                e.g. the bounds `Copy`, `Display` & (implicitly) `Sized` in //                `type Assoc<T: Copy> where T: Display`. This also means that we //                later incorrectly render `where T: ?Sized`. // //                The result of `tcx.explicit_predicates_of` *does* contain them but //                it does not contain the other bounds / predicates we need. //                Either merge those two interned lists somehow or refactor //                `clean_ty_generics` to call `explicit_item_bounds` by itself. </ins> let bounds = tcx.explicit_item_bounds(assoc_item.def_id); let predicates = ty::GenericPredicates { parent: None, predicates: bounds }; let mut generics =

use rustc_data_structures::fx::FxIndexMap; use rustc_hir::def_id::DefId; use rustc_middle::ty; <del> use rustc_span::Symbol; </del> use crate::clean; use crate::clean::GenericArgs as PP;

// // We use `FxIndexMap` so that the insertion order is preserved to prevent messing up to // the order of the generated bounds. <del> let mut params: FxIndexMap<Symbol, (Vec<_>, Vec<_>)> = FxIndexMap::default(); </del> <ins> let mut tybounds = FxIndexMap::default(); </ins> let mut lifetimes = Vec::new(); let mut equalities = Vec::new(); <del> let mut tybounds = Vec::new(); </del> for clause in clauses { match clause { <del> WP::BoundPredicate { ty, bounds, bound_params } => match ty { clean::Generic(s) => { let (b, p) = params.entry(s).or_default(); b.extend(bounds); p.extend(bound_params); } t => tybounds.push((t, (bounds, bound_params))), }, </del> <ins> WP::BoundPredicate { ty, bounds, bound_params } => { let (b, p): &mut (Vec<_>, Vec<_>) = tybounds.entry(ty).or_default(); b.extend(bounds); p.extend(bound_params); } </ins> WP::RegionPredicate { lifetime, bounds } => { lifetimes.push((lifetime, bounds)); }

} // Look for equality predicates on associated types that can be merged into <del> // general bound predicates </del> <ins> // general bound predicates. </ins> equalities.retain(|&(ref lhs, ref rhs)| { <del> let Some((self_, trait_did, name)) = lhs.projection() else { return true; }; let clean::Generic(generic) = self_ else { return true }; let Some((bounds, _)) = params.get_mut(generic) else { return true }; </del> <ins> let Some((ty, trait_did, name)) = lhs.projection() else { return true; }; // FIXME(fmease): We don't handle HRTBs correctly here. //                Pass `_bound_params` (higher-rank lifetimes) to a modified version of //                `merge_bounds`. That vector is currently always empty though since we //                don't keep track of late-bound lifetimes when cleaning projection //                predicates to cleaned equality predicates while we should first query //                them with `collect_referenced_late_bound_regions` and then store them //                (or something similar). For prior art, see `clean::auto_trait`. let Some((bounds, _bound_params)) = tybounds.get_mut(ty) else { return true }; </ins> merge_bounds(cx, bounds, trait_did, name, rhs) });

clauses.extend( lifetimes.into_iter().map(|(lt, bounds)| WP::RegionPredicate { lifetime: lt, bounds }), ); <del> clauses.extend(params.into_iter().map(|(k, (bounds, params))| WP::BoundPredicate { ty: clean::Generic(k), bounds, bound_params: params, })); </del> clauses.extend(tybounds.into_iter().map(|(ty, (bounds, bound_params))| WP::BoundPredicate { ty, bounds,

<ins> <h4 class="code-header">type <a href="#associatedtype.Out0" class="associatedtype">Out0</a>: <a class="trait" href="../assoc_item_trait_bounds_with_bindings/trait.Support.html" title="trait assoc_item_trait_bounds_with_bindings::Support">Support</a>&lt;Item = <a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>&gt;</h4> </ins>  No newline at end of file

<ins> <h4 class="code-header">type <a href="#associatedtype.Out9" class="associatedtype">Out9</a>: <a class="trait" href="{{channel}}/core/ops/function/trait.FnMut.html" title="trait core::ops::function::FnMut">FnMut</a>(<a class="primitive" href="{{channel}}/std/primitive.i32.html">i32</a>) -&gt; <a class="primitive" href="{{channel}}/std/primitive.bool.html">bool</a> + <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a></h4> </ins>  No newline at end of file

<ins> // Regression test for issues #77763, #84579 and #102142. #![crate_name = "main"] // aux-build:assoc_item_trait_bounds_with_bindings.rs // build-aux-docs // ignore-cross-compile extern crate assoc_item_trait_bounds_with_bindings as aux; // FIXME(fmease): Don't render an incorrect `T: ?Sized` where-clause for parameters //                of GATs like `Main::Out{2,4}`. Add a snapshot test once it's fixed. // FIXME(fmease): Print the `for<>` parameter list in the bounds of //                `Main::Out{6,11,12}`. // @has main/trait.Main.html // @has - '//*[@id="associatedtype.Out0"]' 'type Out0: Support<Item = ()>' // @has - '//*[@id="associatedtype.Out1"]' 'type Out1: Support<Item = Self::Item>' // @has - '//*[@id="associatedtype.Out2"]' 'type Out2<T>: Support<Item = T>' // @has - '//*[@id="associatedtype.Out3"]' 'type Out3: Support<Produce<()> = bool>' // @has - '//*[@id="associatedtype.Out4"]' 'type Out4<T>: Support<Produce<T> = T>' // @has - '//*[@id="associatedtype.Out5"]' "type Out5: Support<Output<'static> = &'static ()>" // @has - '//*[@id="associatedtype.Out6"]' "type Out6: Support<Output<'a> = &'a ()>" // @has - '//*[@id="associatedtype.Out7"]' "type Out7: Support<Item = String, Produce<i32> = u32> + Unrelated" // @has - '//*[@id="associatedtype.Out8"]' "type Out8: Unrelated + Protocol<i16, Q1 = u128, Q0 = ()>" // @has - '//*[@id="associatedtype.Out9"]' "type Out9: FnMut(i32) -> bool + Clone" // @has - '//*[@id="associatedtype.Out10"]' "type Out10<'q>: Support<Output<'q> = ()>" // @has - '//*[@id="associatedtype.Out11"]' "type Out11: Helper<A<'s> = &'s (), B<'r> = ()>" // @has - '//*[@id="associatedtype.Out12"]' "type Out12: Helper<B<'w> = Cow<'w, str>, A<'w> = bool>" // // Snapshots: Check that we do not render any where-clauses for those associated types since all of // the trait bounds contained within were moved to the bounds of the respective item. // // @snapshot out0 - '//*[@id="associatedtype.Out0"]/*[@class="code-header"]' // @snapshot out9 - '//*[@id="associatedtype.Out9"]/*[@class="code-header"]' // // @has - '//*[@id="tymethod.make"]'  // "fn make<F>(F, impl FnMut(&str) -> bool) // where  //     F: FnOnce(u32) -> String,  //     Self::Out2<()>: Protocol<u8, Q0 = Self::Item, Q1 = ()>" pub use aux::Main; </ins>

<ins> pub trait Main { type Item; type Out0: Support<Item = ()>; type Out1: Support<Item = Self::Item>; type Out2<T>: Support<Item = T>; type Out3: Support<Produce<()> = bool>; type Out4<T>: Support<Produce<T> = T>; type Out5: Support<Output<'static> = &'static ()>; type Out6: for<'a> Support<Output<'a> = &'a ()>; type Out7: Support<Item = String, Produce<i32> = u32> + Unrelated; type Out8: Unrelated + Protocol<i16, Q1 = u128, Q0 = ()>; type Out9: FnMut(i32) -> bool + Clone; type Out10<'q>: Support<Output<'q> = ()>; type Out11: for<'r, 's> Helper<A<'s> = &'s (), B<'r> = ()>; type Out12: for<'w> Helper<B<'w> = std::borrow::Cow<'w, str>, A<'w> = bool>; fn make<F>(_: F, _: impl FnMut(&str) -> bool) where F: FnOnce(u32) -> String, Self::Out2<()>: Protocol<u8, Q0 = Self::Item, Q1 = ()>; } pub trait Support { type Item; type Output<'a>; type Produce<T>; } pub trait Protocol<K> { type Q0; type Q1; } pub trait Unrelated {} pub trait Helper { type A<'q>; type B<'q>; } </ins>