Change:
let mut where_predicates = where_predicates.into_iter().flat_map(|p| clean_predicate(*p, cx)).collect::<Vec<_>>(); <del> // 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. </del> <ins> // 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`). </ins> // <del> // Note that associated types also have a sized bound by default, but we </del> <ins> // 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 </ins> // don't actually know the set of associated types right here so that's <del> // handled in cleaning associated types </del> <ins> // handled when cleaning associated types. </ins> let mut sized_params = FxHashSet::default(); <del> 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 } </del> <ins> 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 </ins> } <del> _ => true, </del> }); <del> // Run through the type parameters again and insert a ?Sized // unbound for any we didn't find to be Sized. </del> <ins> // 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`. </ins> for tp in &stripped_params { <del> if matches!(tp.kind, types::GenericParamDefKind::Type { .. }) && !sized_params.contains(&tp.name) </del> <ins> if let types::GenericParamDefKind::Type { .. } = tp.kind && !sized_params.contains(&tp.name) </ins> { where_predicates.push(WherePredicate::BoundPredicate { ty: Type::Generic(tp.name),

Discussion:
For example  should have a bound, but we're a little too aggressive about pruning out the bounds. For comparison  does indeed have the bound. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
This also applies to bounds on traits.
This prompted a question on IRC about whether requires , because the bound is not visible in the libstd documentation. It is visible in the libcore docs though.
Triage: This still happens
This actually ended up biting me today, is there a plan to handle this? I could help implement if I get pointers
did not fix this - it now shows , which is nice, but it doesn't show bounds on traits. For traits it does matter because the default is .
I would start by finding out why this is different between local crates and cross-crate re-exports. I expect is behaving differently from .
Ah, I also hit this today when looking at . Kudos to whoever can figure this one out :)
claim