Rollup merge of #103254 - fmease:fix-24183, r=GuillaumeGomez

rustdoc: do not filter out cross-crate `Self: Sized` bounds

All type parameters **except `Self`** are implicitly `Sized` ([via](https://doc.rust-lang.org/nightly/std/marker/trait.Sized.html)). Previously, we disregarded the exception of `Self` and omitted cross-crate `Sized` bounds of *any* type parameter *including* `Self` when rendering.
From now on, we *do* render cross-crate `Self: Sized` bounds.

Most notably, in `std` we now finally properly render the `Sized` bound of the `Clone` trait as well as the `Self: Sized` bound on `Iterator::map`.

Fixes #24183.

``@rustbot`` label T-rustdoc A-cross-crate-reexports
r? rustdoc
This commit is contained in:
Michael Howell 2022-10-23 14:48:16 -07:00 committed by GitHub
commit 28a1bafd48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 56 additions and 18 deletions

View File

@ -774,31 +774,36 @@ fn clean_ty_generics<'tcx>(
let mut where_predicates =
where_predicates.into_iter().flat_map(|p| clean_predicate(*p, cx)).collect::<Vec<_>>();
// Type parameters have a Sized bound by default unless removed with
// ?Sized. Scan through the predicates and mark any type parameter with
// a Sized bound, removing the bounds as we find them.
// In the surface language, all type parameters except `Self` have an
// implicit `Sized` bound unless removed with `?Sized`.
// However, in the list of where-predicates below, `Sized` appears like a
// normal bound: It's either present (the type is sized) or
// absent (the type is unsized) but never *maybe* (i.e. `?Sized`).
//
// Note that associated types also have a sized bound by default, but we
// This is unsuitable for rendering.
// Thus, as a first step remove all `Sized` bounds that should be implicit.
//
// Note that associated types also have an implicit `Sized` bound but we
// don't actually know the set of associated types right here so that's
// handled in cleaning associated types
// handled when cleaning associated types.
let mut sized_params = FxHashSet::default();
where_predicates.retain(|pred| match *pred {
WherePredicate::BoundPredicate { ty: Generic(ref g), ref bounds, .. } => {
if bounds.iter().any(|b| b.is_sized_bound(cx)) {
sized_params.insert(*g);
false
} else {
true
}
where_predicates.retain(|pred| {
if let WherePredicate::BoundPredicate { ty: Generic(g), bounds, .. } = pred
&& *g != kw::SelfUpper
&& bounds.iter().any(|b| b.is_sized_bound(cx))
{
sized_params.insert(*g);
false
} else {
true
}
_ => true,
});
// Run through the type parameters again and insert a ?Sized
// unbound for any we didn't find to be Sized.
// As a final step, go through the type parameters again and insert a
// `?Sized` bound for each one we didn't find to be `Sized`.
for tp in &stripped_params {
if matches!(tp.kind, types::GenericParamDefKind::Type { .. })
&& !sized_params.contains(&tp.name)
if let types::GenericParamDefKind::Type { .. } = tp.kind
&& !sized_params.contains(&tp.name)
{
where_predicates.push(WherePredicate::BoundPredicate {
ty: Type::Generic(tp.name),

View File

@ -0,0 +1,14 @@
#![crate_type = "lib"]
pub trait U/*: ?Sized */ {
fn modified(self) -> Self
where
Self: Sized
{
self
}
fn touch(&self)/* where Self: ?Sized */{}
}
pub trait S: Sized {}

View File

@ -0,0 +1 @@
<h4 class="code-header">fn <a href="#method.touch" class="fnname">touch</a>(&amp;self)</h4>

View File

@ -0,0 +1,18 @@
#![crate_type = "lib"]
#![crate_name = "usr"]
// aux-crate:issue_24183=issue-24183.rs
// edition: 2021
// @has usr/trait.U.html
// @has - '//*[@class="item-decl"]' "pub trait U {"
// @has - '//*[@id="method.modified"]' \
// "fn modified(self) -> Self\
// where \
// Self: Sized"
// @snapshot method_no_where_self_sized - '//*[@id="method.touch"]/*[@class="code-header"]'
pub use issue_24183::U;
// @has usr/trait.S.html
// @has - '//*[@class="item-decl"]' 'pub trait S: Sized {'
pub use issue_24183::S;