1
Fork 0

Auto merge of #84814 - Stupremee:properly-render-hrtbs, r=GuillaumeGomez

Properly render HRTBs

```rust
pub fn test<T>()
where
    for<'a> &'a T: Iterator,
{}
```

This will now render properly including the `for<'a>`
![image](https://user-images.githubusercontent.com/39732259/116808426-fe6ce600-ab38-11eb-9452-f33f554fbb8e.png)

I do not know if this covers all cases, it only covers everything that I could think of that includes `for` and lifetimes in where bounds.
Also someone need to mentor me on how to add a proper rustdoc test for this.

Resolves #78482
This commit is contained in:
bors 2021-06-26 10:52:16 +00:00
commit 831ae3c136
12 changed files with 233 additions and 118 deletions

View file

@ -250,17 +250,33 @@ crate fn print_where_clause<'a, 'tcx: 'a>(
}
match pred {
clean::WherePredicate::BoundPredicate { ty, bounds } => {
clean::WherePredicate::BoundPredicate { ty, bounds, bound_params } => {
let bounds = bounds;
let for_prefix = match bound_params.len() {
0 => String::new(),
_ if f.alternate() => {
format!(
"for<{:#}> ",
comma_sep(bound_params.iter().map(|lt| lt.print()))
)
}
_ => format!(
"for&lt;{}&gt; ",
comma_sep(bound_params.iter().map(|lt| lt.print()))
),
};
if f.alternate() {
clause.push_str(&format!(
"{:#}: {:#}",
"{}{:#}: {:#}",
for_prefix,
ty.print(cx),
print_generic_bounds(bounds, cx)
));
} else {
clause.push_str(&format!(
"{}: {}",
"{}{}: {}",
for_prefix,
ty.print(cx),
print_generic_bounds(bounds, cx)
));
@ -631,18 +647,24 @@ fn primitive_link(
/// Helper to render type parameters
fn tybounds<'a, 'tcx: 'a>(
param_names: &'a Option<Vec<clean::GenericBound>>,
bounds: &'a Vec<clean::PolyTrait>,
lt: &'a Option<clean::Lifetime>,
cx: &'a Context<'tcx>,
) -> impl fmt::Display + 'a + Captures<'tcx> {
display_fn(move |f| match *param_names {
Some(ref params) => {
for param in params {
display_fn(move |f| {
for (i, bound) in bounds.iter().enumerate() {
if i > 0 {
write!(f, " + ")?;
fmt::Display::fmt(&param.print(cx), f)?;
}
Ok(())
fmt::Display::fmt(&bound.print(cx), f)?;
}
None => Ok(()),
if let Some(lt) = lt {
write!(f, " + ")?;
fmt::Display::fmt(&lt.print(), f)?;
}
Ok(())
})
}
@ -679,13 +701,13 @@ fn fmt_type<'cx>(
match *t {
clean::Generic(name) => write!(f, "{}", name),
clean::ResolvedPath { did, ref param_names, ref path, is_generic } => {
if param_names.is_some() {
f.write_str("dyn ")?;
}
clean::ResolvedPath { did, ref path, is_generic } => {
// Paths like `T::Output` and `Self::Output` should be rendered with all segments.
resolved_path(f, did, path, is_generic, use_absolute, cx)?;
fmt::Display::fmt(&tybounds(param_names, cx), f)
resolved_path(f, did, path, is_generic, use_absolute, cx)
}
clean::DynTrait(ref bounds, ref lt) => {
f.write_str("dyn ")?;
fmt::Display::fmt(&tybounds(bounds, lt, cx), f)
}
clean::Infer => write!(f, "_"),
clean::Primitive(prim) => primitive_link(f, prim, &*prim.as_sym().as_str(), cx),
@ -820,7 +842,9 @@ fn fmt_type<'cx>(
}
}
}
clean::ResolvedPath { param_names: Some(ref v), .. } if !v.is_empty() => {
clean::DynTrait(ref bounds, ref trait_lt)
if bounds.len() > 1 || trait_lt.is_some() =>
{
write!(f, "{}{}{}(", amp, lt, m)?;
fmt_type(&ty, f, use_absolute, cx)?;
write!(f, ")")
@ -881,7 +905,7 @@ fn fmt_type<'cx>(
// the ugliness comes from inlining across crates where
// everything comes in as a fully resolved QPath (hard to
// look at).
box clean::ResolvedPath { did, ref param_names, .. } => {
box clean::ResolvedPath { did, .. } => {
match href(did.into(), cx) {
Some((ref url, _, ref path)) if !f.alternate() => {
write!(
@ -896,9 +920,6 @@ fn fmt_type<'cx>(
}
_ => write!(f, "{}", name)?,
}
// FIXME: `param_names` are not rendered, and this seems bad?
drop(param_names);
Ok(())
}
_ => write!(f, "{}", name),