From 2cc4a0aad72752a4d485ced76bab677620f088b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 18 Oct 2022 15:34:41 +0200 Subject: [PATCH] rustdoc: render bounds of cross-crate GAT params --- src/librustdoc/clean/mod.rs | 44 +++++++++++++------ .../assoc_item_trait_bounds.out0.html | 1 + .../assoc_item_trait_bounds.out2.html | 1 + ...html => assoc_item_trait_bounds.out9.html} | 0 ...bindings.rs => assoc_item_trait_bounds.rs} | 15 ++++--- ..._item_trait_bounds_with_bindings.out0.html | 1 - ...bindings.rs => assoc_item_trait_bounds.rs} | 1 + 7 files changed, 41 insertions(+), 22 deletions(-) create mode 100644 src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out0.html create mode 100644 src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out2.html rename src/test/rustdoc/inline_cross/{assoc_item_trait_bounds_with_bindings.out9.html => assoc_item_trait_bounds.out9.html} (100%) rename src/test/rustdoc/inline_cross/{assoc_item_trait_bounds_with_bindings.rs => assoc_item_trait_bounds.rs} (79%) delete mode 100644 src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.out0.html rename src/test/rustdoc/inline_cross/auxiliary/{assoc_item_trait_bounds_with_bindings.rs => assoc_item_trait_bounds.rs} (96%) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 5f674ed7441ba..13d63ffa0ee3c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1201,21 +1201,19 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( } if let ty::TraitContainer = assoc_item.container { - // FIXME(fmease): `tcx.explicit_item_bounds` does not contain the bounds of GATs, - // e.g. the bounds `Copy`, `Display` & (implicitly) `Sized` in - // `type Assoc 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. let bounds = tcx.explicit_item_bounds(assoc_item.def_id); - let predicates = ty::GenericPredicates { parent: None, predicates: bounds }; - let mut generics = - clean_ty_generics(cx, tcx.generics_of(assoc_item.def_id), predicates); - // Filter out the bounds that are (likely?) directly attached to the associated type, - // as opposed to being located in the where clause. + let predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates; + let predicates = + tcx.arena.alloc_from_iter(bounds.into_iter().chain(predicates).copied()); + let mut generics = clean_ty_generics( + cx, + tcx.generics_of(assoc_item.def_id), + ty::GenericPredicates { parent: None, predicates }, + ); + // Move bounds that are (likely) directly attached to the associated type + // from the where clause to the associated type. + // There is no guarantee that this is what the user actually wrote but we have + // no way of knowing. let mut bounds = generics .where_predicates .drain_filter(|pred| match *pred { @@ -1273,6 +1271,24 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( } None => bounds.push(GenericBound::maybe_sized(cx)), } + // Move bounds that are (likely) directly attached to the parameters of the + // (generic) associated type from the where clause to the respective parameter. + // There is no guarantee that this is what the user actually wrote but we have + // no way of knowing. + let mut where_predicates = Vec::new(); + for mut pred in generics.where_predicates { + if let WherePredicate::BoundPredicate { ty: Generic(arg), bounds, .. } = &mut pred + && let Some(GenericParamDef { + kind: GenericParamDefKind::Type { bounds: param_bounds, .. }, + .. + }) = generics.params.iter_mut().find(|param| ¶m.name == arg) + { + param_bounds.extend(mem::take(bounds)); + } else { + where_predicates.push(pred); + } + } + generics.where_predicates = where_predicates; if tcx.impl_defaultness(assoc_item.def_id).has_value() { AssocTypeItem( diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out0.html b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out0.html new file mode 100644 index 0000000000000..8934bc1ee339c --- /dev/null +++ b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out0.html @@ -0,0 +1 @@ +

type Out0: Support<Item = ()>

\ No newline at end of file diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out2.html b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out2.html new file mode 100644 index 0000000000000..bf330670ed0fa --- /dev/null +++ b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out2.html @@ -0,0 +1 @@ +

type Out2<T>: Support<Item = T>

\ No newline at end of file diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.out9.html b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out9.html similarity index 100% rename from src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.out9.html rename to src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out9.html diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.rs b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs similarity index 79% rename from src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.rs rename to src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs index 00976aa74420f..5f4712aab5b19 100644 --- a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.rs +++ b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs @@ -1,13 +1,10 @@ // Regression test for issues #77763, #84579 and #102142. #![crate_name = "main"] -// aux-build:assoc_item_trait_bounds_with_bindings.rs +// aux-build:assoc_item_trait_bounds.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. +extern crate assoc_item_trait_bounds as aux; // @has main/trait.Main.html // @has - '//*[@id="associatedtype.Out0"]' 'type Out0: Support' @@ -24,11 +21,15 @@ extern crate assoc_item_trait_bounds_with_bindings as aux; // @has - '//*[@id="associatedtype.Out11"]' "type Out11: for<'r, 's> Helper = &'s (), B<'r> = ()>" // @has - '//*[@id="associatedtype.Out12"]' "type Out12: for<'w> Helper = Cow<'w, str>, A<'w> = bool>" // @has - '//*[@id="associatedtype.Out13"]' "type Out13: for<'fst, 'snd> Aid<'snd, Result<'fst> = &'fst mut str>" +// @has - '//*[@id="associatedtype.Out14"]' "type Out14" // -// 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. +// Snapshots: +// Check that we don't render any where-clauses for the following associated types since +// all corresponding projection equality predicates should have already been re-sugared +// to associated type bindings: // // @snapshot out0 - '//*[@id="associatedtype.Out0"]/*[@class="code-header"]' +// @snapshot out2 - '//*[@id="associatedtype.Out2"]/*[@class="code-header"]' // @snapshot out9 - '//*[@id="associatedtype.Out9"]/*[@class="code-header"]' // // @has - '//*[@id="tymethod.make"]' \ diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.out0.html b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.out0.html deleted file mode 100644 index 927a1a42a1f78..0000000000000 --- a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.out0.html +++ /dev/null @@ -1 +0,0 @@ -

type Out0: Support<Item = ()>

\ No newline at end of file diff --git a/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds_with_bindings.rs b/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs similarity index 96% rename from src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds_with_bindings.rs rename to src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs index f451b1a0e9920..d326e61daea26 100644 --- a/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds_with_bindings.rs +++ b/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs @@ -15,6 +15,7 @@ pub trait Main { type Out11: for<'r, 's> Helper = &'s (), B<'r> = ()>; type Out12: for<'w> Helper = std::borrow::Cow<'w, str>, A<'w> = bool>; type Out13: for<'fst, 'snd> Aid<'snd, Result<'fst> = &'fst mut str>; + type Out14; fn make(_: F, _: impl FnMut(&str) -> bool) where