From 438ca19b356382fb6555fbe7605b19cc862bd79a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= <me@fmease.dev>
Date: Wed, 28 Feb 2024 08:13:29 +0100
Subject: [PATCH 1/2] rustdoc: pass owner item of generics to cleaning
 functions

---
 src/librustdoc/clean/auto_trait.rs   |   2 +
 src/librustdoc/clean/blanket_impl.rs |   1 +
 src/librustdoc/clean/inline.rs       |  30 ++++---
 src/librustdoc/clean/mod.rs          | 121 +++++++++++++++------------
 4 files changed, 91 insertions(+), 63 deletions(-)

diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index fbc2c3c5af459..ae756f2b1fc74 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -106,6 +106,7 @@ where
                     self.cx,
                     tcx.generics_of(item_def_id),
                     ty::GenericPredicates::default(),
+                    item_def_id,
                 );
                 let params = raw_generics.params;
 
@@ -456,6 +457,7 @@ where
             self.cx,
             tcx.generics_of(item_def_id),
             tcx.explicit_predicates_of(item_def_id),
+            item_def_id,
         );
         let mut generic_params = raw_generics.params;
 
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index 47cfe651e319d..983d3be2d474c 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -101,6 +101,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                             cx,
                             cx.tcx.generics_of(impl_def_id),
                             cx.tcx.explicit_predicates_of(impl_def_id),
+                            impl_def_id,
                         ),
                         // FIXME(eddyb) compute both `trait_` and `for_` from
                         // the post-inference `trait_ref`, as it's more accurate.
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 03f62f41a26f4..3486a986c88eb 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -270,7 +270,7 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean
         .collect();
 
     let predicates = cx.tcx.predicates_of(did);
-    let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates);
+    let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates, did);
     let generics = filter_non_trait_generics(did, generics);
     let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
     clean::Trait { def_id: did, generics, items: trait_items, bounds: supertrait_bounds }
@@ -282,8 +282,12 @@ pub(crate) fn build_function<'tcx>(
 ) -> Box<clean::Function> {
     let sig = cx.tcx.fn_sig(def_id).instantiate_identity();
     // The generics need to be cleaned before the signature.
-    let mut generics =
-        clean_ty_generics(cx, cx.tcx.generics_of(def_id), cx.tcx.explicit_predicates_of(def_id));
+    let mut generics = clean_ty_generics(
+        cx,
+        cx.tcx.generics_of(def_id),
+        cx.tcx.explicit_predicates_of(def_id),
+        def_id,
+    );
     let bound_vars = clean_bound_vars(sig.bound_vars());
 
     // At the time of writing early & late-bound params are stored separately in rustc,
@@ -315,7 +319,7 @@ fn build_enum(cx: &mut DocContext<'_>, did: DefId) -> clean::Enum {
     let predicates = cx.tcx.explicit_predicates_of(did);
 
     clean::Enum {
-        generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates),
+        generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates, did),
         variants: cx.tcx.adt_def(did).variants().iter().map(|v| clean_variant_def(v, cx)).collect(),
     }
 }
@@ -326,7 +330,7 @@ fn build_struct(cx: &mut DocContext<'_>, did: DefId) -> clean::Struct {
 
     clean::Struct {
         ctor_kind: variant.ctor_kind(),
-        generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates),
+        generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates, did),
         fields: variant.fields.iter().map(|x| clean_middle_field(x, cx)).collect(),
     }
 }
@@ -335,7 +339,7 @@ fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union {
     let predicates = cx.tcx.explicit_predicates_of(did);
     let variant = cx.tcx.adt_def(did).non_enum_variant();
 
-    let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates);
+    let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates, did);
     let fields = variant.fields.iter().map(|x| clean_middle_field(x, cx)).collect();
     clean::Union { generics, fields }
 }
@@ -352,7 +356,7 @@ fn build_type_alias(
 
     Box::new(clean::TypeAlias {
         type_,
-        generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates),
+        generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates, did),
         inner_type,
         item_type: None,
     })
@@ -530,7 +534,7 @@ pub(crate) fn build_impl(
                 })
                 .map(|item| clean_impl_item(item, cx))
                 .collect::<Vec<_>>(),
-            clean_generics(impl_.generics, cx),
+            clean_generics(impl_.generics, cx, did),
         ),
         None => (
             tcx.associated_items(did)
@@ -558,7 +562,7 @@ pub(crate) fn build_impl(
                 .map(|item| clean_middle_assoc_item(item, cx))
                 .collect::<Vec<_>>(),
             clean::enter_impl_trait(cx, |cx| {
-                clean_ty_generics(cx, tcx.generics_of(did), predicates)
+                clean_ty_generics(cx, tcx.generics_of(did), predicates, did)
             }),
         ),
     };
@@ -716,8 +720,12 @@ pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
 }
 
 fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant {
-    let mut generics =
-        clean_ty_generics(cx, cx.tcx.generics_of(def_id), cx.tcx.explicit_predicates_of(def_id));
+    let mut generics = clean_ty_generics(
+        cx,
+        cx.tcx.generics_of(def_id),
+        cx.tcx.explicit_predicates_of(def_id),
+        def_id,
+    );
     clean::simplify::move_bounds_to_generic_parameters(&mut generics);
 
     clean::Constant {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index b32d3ad562d03..f4110428e5c27 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -631,22 +631,18 @@ fn is_elided_lifetime(param: &hir::GenericParam<'_>) -> bool {
 }
 
 pub(crate) fn clean_generics<'tcx>(
-    gens: &hir::Generics<'tcx>,
+    generics: &hir::Generics<'tcx>,
     cx: &mut DocContext<'tcx>,
+    _item_def_id: DefId,
 ) -> Generics {
-    let impl_trait_params = gens
+    let impl_trait_params = generics
         .params
         .iter()
         .filter(|param| is_impl_trait(param))
         .map(|param| {
-            let param = clean_generic_param(cx, Some(gens), param);
-            match param.kind {
-                GenericParamDefKind::Lifetime { .. } => unreachable!(),
-                GenericParamDefKind::Type { ref bounds, .. } => {
-                    cx.impl_trait_bounds.insert(param.def_id.into(), bounds.to_vec());
-                }
-                GenericParamDefKind::Const { .. } => unreachable!(),
-            }
+            let param = clean_generic_param(cx, Some(generics), param);
+            let GenericParamDefKind::Type { bounds, .. } = &param.kind else { unreachable!() };
+            cx.impl_trait_bounds.insert(param.def_id.into(), bounds.to_vec());
             param
         })
         .collect::<Vec<_>>();
@@ -654,7 +650,7 @@ pub(crate) fn clean_generics<'tcx>(
     let mut bound_predicates = FxIndexMap::default();
     let mut region_predicates = FxIndexMap::default();
     let mut eq_predicates = ThinVec::default();
-    for pred in gens.predicates.iter().filter_map(|x| clean_where_predicate(x, cx)) {
+    for pred in generics.predicates.iter().filter_map(|x| clean_where_predicate(x, cx)) {
         match pred {
             WherePredicate::BoundPredicate { ty, bounds, bound_params } => {
                 match bound_predicates.entry(ty) {
@@ -697,15 +693,15 @@ pub(crate) fn clean_generics<'tcx>(
         }
     }
 
-    let mut params = ThinVec::with_capacity(gens.params.len());
+    let mut params = ThinVec::with_capacity(generics.params.len());
     // In this loop, we gather the generic parameters (`<'a, B: 'a>`) and check if they have
     // bounds in the where predicates. If so, we move their bounds into the where predicates
     // while also preventing duplicates.
-    for p in gens.params.iter().filter(|p| !is_impl_trait(p) && !is_elided_lifetime(p)) {
-        let mut p = clean_generic_param(cx, Some(gens), p);
-        match &mut p.kind {
-            GenericParamDefKind::Lifetime { ref mut outlives } => {
-                if let Some(region_pred) = region_predicates.get_mut(&Lifetime(p.name)) {
+    for param in generics.params.iter().filter(|p| !is_impl_trait(p) && !is_elided_lifetime(p)) {
+        let mut param = clean_generic_param(cx, Some(generics), param);
+        match &mut param.kind {
+            GenericParamDefKind::Lifetime { outlives } => {
+                if let Some(region_pred) = region_predicates.get_mut(&Lifetime(param.name)) {
                     // We merge bounds in the `where` clause.
                     for outlive in outlives.drain(..) {
                         let outlive = GenericBound::Outlives(outlive);
@@ -716,7 +712,7 @@ pub(crate) fn clean_generics<'tcx>(
                 }
             }
             GenericParamDefKind::Type { bounds, synthetic: false, .. } => {
-                if let Some(bound_pred) = bound_predicates.get_mut(&Type::Generic(p.name)) {
+                if let Some(bound_pred) = bound_predicates.get_mut(&Type::Generic(param.name)) {
                     // We merge bounds in the `where` clause.
                     for bound in bounds.drain(..) {
                         if !bound_pred.0.contains(&bound) {
@@ -729,7 +725,7 @@ pub(crate) fn clean_generics<'tcx>(
                 // nothing to do here.
             }
         }
-        params.push(p);
+        params.push(param);
     }
     params.extend(impl_trait_params);
 
@@ -754,8 +750,9 @@ pub(crate) fn clean_generics<'tcx>(
 
 fn clean_ty_generics<'tcx>(
     cx: &mut DocContext<'tcx>,
-    gens: &ty::Generics,
-    preds: ty::GenericPredicates<'tcx>,
+    generics: &ty::Generics,
+    predicates: ty::GenericPredicates<'tcx>,
+    _item_def_id: DefId,
 ) -> Generics {
     // Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses,
     // since `Clean for ty::Predicate` would consume them.
@@ -764,7 +761,7 @@ fn clean_ty_generics<'tcx>(
     // Bounds in the type_params and lifetimes fields are repeated in the
     // predicates field (see rustc_hir_analysis::collect::ty_generics), so remove
     // them.
-    let stripped_params = gens
+    let stripped_params = generics
         .params
         .iter()
         .filter_map(|param| match param.kind {
@@ -790,7 +787,7 @@ fn clean_ty_generics<'tcx>(
     let mut impl_trait_proj =
         FxHashMap::<u32, Vec<(DefId, PathSegment, ty::Binder<'_, ty::Term<'_>>)>>::default();
 
-    let where_predicates = preds
+    let where_predicates = predicates
         .predicates
         .iter()
         .flat_map(|(pred, _)| {
@@ -1040,7 +1037,13 @@ fn clean_fn_or_proc_macro<'tcx>(
     match macro_kind {
         Some(kind) => clean_proc_macro(item, name, kind, cx),
         None => {
-            let mut func = clean_function(cx, sig, generics, FunctionArgs::Body(body_id));
+            let mut func = clean_function(
+                cx,
+                item.owner_id.to_def_id(),
+                sig,
+                generics,
+                FunctionArgs::Body(body_id),
+            );
             clean_fn_decl_legacy_const_generics(&mut func, attrs);
             FunctionItem(func)
         }
@@ -1087,13 +1090,14 @@ enum FunctionArgs<'tcx> {
 
 fn clean_function<'tcx>(
     cx: &mut DocContext<'tcx>,
+    did: DefId,
     sig: &hir::FnSig<'tcx>,
     generics: &hir::Generics<'tcx>,
     args: FunctionArgs<'tcx>,
 ) -> Box<Function> {
     let (generics, decl) = enter_impl_trait(cx, |cx| {
         // NOTE: generics must be cleaned before args
-        let generics = clean_generics(generics, cx);
+        let generics = clean_generics(generics, cx, did);
         let args = match args {
             FunctionArgs::Body(body_id) => {
                 clean_args_from_types_and_body_id(cx, sig.decl.inputs, body_id)
@@ -1232,31 +1236,41 @@ fn clean_poly_trait_ref<'tcx>(
 }
 
 fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
-    let local_did = trait_item.owner_id.to_def_id();
-    cx.with_param_env(local_did, |cx| {
+    let def_id = trait_item.owner_id.to_def_id();
+    cx.with_param_env(def_id, |cx| {
         let inner = match trait_item.kind {
             hir::TraitItemKind::Const(ty, Some(default)) => {
-                let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
+                let generics =
+                    enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx, def_id));
                 AssocConstItem(
                     generics,
                     Box::new(clean_ty(ty, cx)),
-                    ConstantKind::Local { def_id: local_did, body: default },
+                    ConstantKind::Local { def_id, body: default },
                 )
             }
             hir::TraitItemKind::Const(ty, None) => {
-                let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
+                let generics =
+                    enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx, def_id));
                 TyAssocConstItem(generics, Box::new(clean_ty(ty, cx)))
             }
             hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
-                let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Body(body));
+                let m =
+                    clean_function(cx, def_id, sig, trait_item.generics, FunctionArgs::Body(body));
                 MethodItem(m, None)
             }
             hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(names)) => {
-                let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Names(names));
+                let m = clean_function(
+                    cx,
+                    def_id,
+                    sig,
+                    trait_item.generics,
+                    FunctionArgs::Names(names),
+                );
                 TyMethodItem(m)
             }
             hir::TraitItemKind::Type(bounds, Some(default)) => {
-                let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
+                let generics =
+                    enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx, def_id));
                 let bounds = bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect();
                 let item_type = clean_middle_ty(
                     ty::Binder::dummy(hir_ty_to_ty(cx.tcx, default)),
@@ -1275,12 +1289,13 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
                 )
             }
             hir::TraitItemKind::Type(bounds, None) => {
-                let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
+                let generics =
+                    enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx, def_id));
                 let bounds = bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect();
                 TyAssocTypeItem(generics, bounds)
             }
         };
-        Item::from_def_id_and_parts(local_did, Some(trait_item.ident.name), inner, cx)
+        Item::from_def_id_and_parts(def_id, Some(trait_item.ident.name), inner, cx)
     })
 }
 
@@ -1288,22 +1303,22 @@ pub(crate) fn clean_impl_item<'tcx>(
     impl_: &hir::ImplItem<'tcx>,
     cx: &mut DocContext<'tcx>,
 ) -> Item {
-    let local_did = impl_.owner_id.to_def_id();
-    cx.with_param_env(local_did, |cx| {
+    let def_id = impl_.owner_id.to_def_id();
+    cx.with_param_env(def_id, |cx| {
         let inner = match impl_.kind {
             hir::ImplItemKind::Const(ty, expr) => {
-                let generics = clean_generics(impl_.generics, cx);
-                let default = ConstantKind::Local { def_id: local_did, body: expr };
+                let generics = clean_generics(impl_.generics, cx, def_id);
+                let default = ConstantKind::Local { def_id, body: expr };
                 AssocConstItem(generics, Box::new(clean_ty(ty, cx)), default)
             }
             hir::ImplItemKind::Fn(ref sig, body) => {
-                let m = clean_function(cx, sig, impl_.generics, FunctionArgs::Body(body));
+                let m = clean_function(cx, def_id, sig, impl_.generics, FunctionArgs::Body(body));
                 let defaultness = cx.tcx.defaultness(impl_.owner_id);
                 MethodItem(m, Some(defaultness))
             }
             hir::ImplItemKind::Type(hir_ty) => {
                 let type_ = clean_ty(hir_ty, cx);
-                let generics = clean_generics(impl_.generics, cx);
+                let generics = clean_generics(impl_.generics, cx, def_id);
                 let item_type = clean_middle_ty(
                     ty::Binder::dummy(hir_ty_to_ty(cx.tcx, hir_ty)),
                     cx,
@@ -1322,7 +1337,7 @@ pub(crate) fn clean_impl_item<'tcx>(
             }
         };
 
-        Item::from_def_id_and_parts(local_did, Some(impl_.ident.name), inner, cx)
+        Item::from_def_id_and_parts(def_id, Some(impl_.ident.name), inner, cx)
     })
 }
 
@@ -1344,6 +1359,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
                 cx,
                 tcx.generics_of(assoc_item.def_id),
                 tcx.explicit_predicates_of(assoc_item.def_id),
+                assoc_item.def_id,
             );
             simplify::move_bounds_to_generic_parameters(&mut generics);
 
@@ -1428,6 +1444,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
                 cx,
                 tcx.generics_of(assoc_item.def_id),
                 ty::GenericPredicates { parent: None, predicates },
+                assoc_item.def_id,
             );
             simplify::move_bounds_to_generic_parameters(&mut generics);
 
@@ -2731,12 +2748,12 @@ fn clean_maybe_renamed_item<'tcx>(
             }
             ItemKind::Const(ty, generics, body_id) => ConstantItem(Constant {
                 type_: Box::new(clean_ty(ty, cx)),
-                generics: clean_generics(generics, cx),
+                generics: clean_generics(generics, cx, def_id),
                 kind: ConstantKind::Local { body: body_id, def_id },
             }),
             ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
                 bounds: ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
-                generics: clean_generics(ty.generics, cx),
+                generics: clean_generics(ty.generics, cx, def_id),
             }),
             ItemKind::TyAlias(hir_ty, generics) => {
                 *cx.current_type_aliases.entry(def_id).or_insert(0) += 1;
@@ -2747,7 +2764,7 @@ fn clean_maybe_renamed_item<'tcx>(
                     None,
                     None,
                 );
-                let generics = clean_generics(generics, cx);
+                let generics = clean_generics(generics, cx, def_id);
                 if let Some(count) = cx.current_type_aliases.get_mut(&def_id) {
                     *count -= 1;
                     if *count == 0 {
@@ -2777,19 +2794,19 @@ fn clean_maybe_renamed_item<'tcx>(
             }
             ItemKind::Enum(ref def, generics) => EnumItem(Enum {
                 variants: def.variants.iter().map(|v| clean_variant(v, cx)).collect(),
-                generics: clean_generics(generics, cx),
+                generics: clean_generics(generics, cx, def_id),
             }),
             ItemKind::TraitAlias(generics, bounds) => TraitAliasItem(TraitAlias {
-                generics: clean_generics(generics, cx),
+                generics: clean_generics(generics, cx, def_id),
                 bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
             }),
             ItemKind::Union(ref variant_data, generics) => UnionItem(Union {
-                generics: clean_generics(generics, cx),
+                generics: clean_generics(generics, cx, def_id),
                 fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
             }),
             ItemKind::Struct(ref variant_data, generics) => StructItem(Struct {
                 ctor_kind: variant_data.ctor_kind(),
-                generics: clean_generics(generics, cx),
+                generics: clean_generics(generics, cx, def_id),
                 fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
             }),
             ItemKind::Impl(impl_) => return clean_impl(impl_, item.owner_id.def_id, cx),
@@ -2813,7 +2830,7 @@ fn clean_maybe_renamed_item<'tcx>(
                 TraitItem(Box::new(Trait {
                     def_id,
                     items,
-                    generics: clean_generics(generics, cx),
+                    generics: clean_generics(generics, cx, def_id),
                     bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
                 }))
             }
@@ -2876,7 +2893,7 @@ fn clean_impl<'tcx>(
     let mut make_item = |trait_: Option<Path>, for_: Type, items: Vec<Item>| {
         let kind = ImplItem(Box::new(Impl {
             unsafety: impl_.unsafety,
-            generics: clean_generics(impl_.generics, cx),
+            generics: clean_generics(impl_.generics, cx, def_id.to_def_id()),
             trait_,
             for_,
             items,
@@ -3086,7 +3103,7 @@ fn clean_maybe_renamed_foreign_item<'tcx>(
             hir::ForeignItemKind::Fn(decl, names, generics) => {
                 let (generics, decl) = enter_impl_trait(cx, |cx| {
                     // NOTE: generics must be cleaned before args
-                    let generics = clean_generics(generics, cx);
+                    let generics = clean_generics(generics, cx, def_id);
                     let args = clean_args_from_types_and_names(cx, decl.inputs, names);
                     let decl = clean_fn_decl_with_args(cx, decl, None, args);
                     (generics, decl)

From a981f2c7ee3b299199ed8708b323b2e62d4d59a6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= <me@fmease.dev>
Date: Wed, 28 Feb 2024 13:43:06 +0100
Subject: [PATCH 2/2] [experiments]

---
 src/librustdoc/clean/inline.rs |  3 +++
 src/librustdoc/clean/mod.rs    | 42 ++++++++++++++++++++++++++++++++--
 2 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 3486a986c88eb..d019c75545d16 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -310,6 +310,9 @@ pub(crate) fn build_function<'tcx>(
         generics.params.sort_by_key(|param| cx.tcx.def_ident_span(param.def_id).unwrap());
     }
 
+    // FIXME(fmease): @Temporary
+    crate::clean::simplify::move_bounds_to_generic_parameters(&mut generics);
+
     let decl = clean_poly_fn_sig(cx, Some(def_id), sig);
 
     Box::new(clean::Function { decl, generics })
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index f4110428e5c27..67196b002ae9a 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -750,7 +750,7 @@ pub(crate) fn clean_generics<'tcx>(
 
 fn clean_ty_generics<'tcx>(
     cx: &mut DocContext<'tcx>,
-    generics: &ty::Generics,
+    generics: &'tcx ty::Generics,
     predicates: ty::GenericPredicates<'tcx>,
     _item_def_id: DefId,
 ) -> Generics {
@@ -787,10 +787,48 @@ fn clean_ty_generics<'tcx>(
     let mut impl_trait_proj =
         FxHashMap::<u32, Vec<(DefId, PathSegment, ty::Binder<'_, ty::Term<'_>>)>>::default();
 
+    let item_span = {
+        if !predicates.predicates.is_empty() {
+            let span = cx.tcx.def_span(_item_def_id);
+            // FIXME: this is not correct if spans come from different expansions!
+            let params_sp = {
+                let mut params = generics.params.iter();
+                if let Some(param) = params.next() {
+                    let mut sp = cx.tcx.def_ident_span(param.def_id).unwrap();
+                    while let Some(param) = params.next() {
+                        sp = sp.to(cx.tcx.def_ident_span(param.def_id).unwrap());
+                    }
+                    sp
+                } else {
+                    None
+                }
+            };
+
+            Some(span)
+        } else {
+            None
+        }
+    };
+
     let where_predicates = predicates
         .predicates
         .iter()
-        .flat_map(|(pred, _)| {
+        .flat_map(|(pred, span)| {
+            if !(span.is_dummy()
+                || span.is_empty()
+                || span.from_expansion()
+                || !cx.tcx.sess.source_map().is_span_accessible(*span))
+            {
+                let mut diag = cx.tcx.dcx().struct_span_warn(*span, format!("pred={pred:?}"));
+
+                if let Some(item_span) = item_span {
+                    diag.span_note(item_span, "span");
+                    diag.note(if item_span.contains(*span) { "<...>" } else { "where ... " });
+                }
+
+                diag.emit();
+            }
+
             let mut projection = None;
             let param_idx = (|| {
                 let bound_p = pred.kind();