Rollup merge of #148585 - GuillaumeGomez:improve-format-code, r=yotamofek

[rustdoc] Replace `print` methods with functions to improve code readability

We have a lot of `print` methods, making it quite tricky to know what the types we're manipulating are.

We did something similar with `Clean` trait a few years ago (the first PR was https://github.com/rust-lang/rust/pull/99638, followed by a lot of them).

Each commit replaces one type for easier review.

r? `````@yotamofek`````
This commit is contained in:
Matthias Krüger 2025-11-08 15:42:25 +01:00 committed by GitHub
commit f2beff65ca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 445 additions and 438 deletions

View file

@ -47,71 +47,69 @@ pub(crate) fn print_generic_bounds(
bounds
.iter()
.filter(move |b| bounds_dup.insert(*b))
.map(|bound| bound.print(cx))
.map(|bound| print_generic_bound(bound, cx))
.joined(" + ", f)
})
}
impl clean::GenericParamDef {
pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
fmt::from_fn(move |f| match &self.kind {
clean::GenericParamDefKind::Lifetime { outlives } => {
write!(f, "{}", self.name)?;
pub(crate) fn print_generic_param_def(
generic_param: &clean::GenericParamDef,
cx: &Context<'_>,
) -> impl Display {
fmt::from_fn(move |f| match &generic_param.kind {
clean::GenericParamDefKind::Lifetime { outlives } => {
write!(f, "{}", generic_param.name)?;
if !outlives.is_empty() {
f.write_str(": ")?;
outlives.iter().map(|lt| lt.print()).joined(" + ", f)?;
}
Ok(())
if !outlives.is_empty() {
f.write_str(": ")?;
outlives.iter().map(|lt| print_lifetime(lt)).joined(" + ", f)?;
}
clean::GenericParamDefKind::Type { bounds, default, .. } => {
f.write_str(self.name.as_str())?;
if !bounds.is_empty() {
f.write_str(": ")?;
print_generic_bounds(bounds, cx).fmt(f)?;
}
Ok(())
}
clean::GenericParamDefKind::Type { bounds, default, .. } => {
f.write_str(generic_param.name.as_str())?;
if let Some(ty) = default {
f.write_str(" = ")?;
ty.print(cx).fmt(f)?;
}
Ok(())
if !bounds.is_empty() {
f.write_str(": ")?;
print_generic_bounds(bounds, cx).fmt(f)?;
}
clean::GenericParamDefKind::Const { ty, default, .. } => {
write!(f, "const {}: ", self.name)?;
ty.print(cx).fmt(f)?;
if let Some(default) = default {
f.write_str(" = ")?;
if f.alternate() {
write!(f, "{default}")?;
} else {
write!(f, "{}", Escape(default))?;
}
}
Ok(())
if let Some(ty) = default {
f.write_str(" = ")?;
print_type(ty, cx).fmt(f)?;
}
})
}
Ok(())
}
clean::GenericParamDefKind::Const { ty, default, .. } => {
write!(f, "const {}: ", generic_param.name)?;
print_type(ty, cx).fmt(f)?;
if let Some(default) = default {
f.write_str(" = ")?;
if f.alternate() {
write!(f, "{default}")?;
} else {
write!(f, "{}", Escape(default))?;
}
}
Ok(())
}
})
}
impl clean::Generics {
pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
let mut real_params = self.params.iter().filter(|p| !p.is_synthetic_param()).peekable();
if real_params.peek().is_none() {
None
} else {
Some(
Wrapped::with_angle_brackets()
.wrap_fn(move |f| real_params.clone().map(|g| g.print(cx)).joined(", ", f)),
)
}
.maybe_display()
pub(crate) fn print_generics(generics: &clean::Generics, cx: &Context<'_>) -> impl Display {
let mut real_params = generics.params.iter().filter(|p| !p.is_synthetic_param()).peekable();
if real_params.peek().is_none() {
None
} else {
Some(Wrapped::with_angle_brackets().wrap_fn(move |f| {
real_params.clone().map(|g| print_generic_param_def(g, cx)).joined(", ", f)
}))
}
.maybe_display()
}
#[derive(Clone, Copy, PartialEq, Eq)]
@ -125,7 +123,7 @@ fn print_where_predicate(predicate: &clean::WherePredicate, cx: &Context<'_>) ->
match predicate {
clean::WherePredicate::BoundPredicate { ty, bounds, bound_params } => {
print_higher_ranked_params_with_space(bound_params, cx, "for").fmt(f)?;
ty.print(cx).fmt(f)?;
print_type(ty, cx).fmt(f)?;
f.write_str(":")?;
if !bounds.is_empty() {
f.write_str(" ")?;
@ -136,7 +134,7 @@ fn print_where_predicate(predicate: &clean::WherePredicate, cx: &Context<'_>) ->
clean::WherePredicate::RegionPredicate { lifetime, bounds } => {
// We don't need to check `alternate` since we can be certain that neither
// the lifetime nor the bounds contain any characters which need escaping.
write!(f, "{}:", lifetime.print())?;
write!(f, "{}:", print_lifetime(lifetime))?;
if !bounds.is_empty() {
write!(f, " {}", print_generic_bounds(bounds, cx))?;
}
@ -144,7 +142,12 @@ fn print_where_predicate(predicate: &clean::WherePredicate, cx: &Context<'_>) ->
}
clean::WherePredicate::EqPredicate { lhs, rhs } => {
let opts = WithOpts::from(f);
write!(f, "{} == {}", opts.display(lhs.print(cx)), opts.display(rhs.print(cx)))
write!(
f,
"{} == {}",
opts.display(print_qpath_data(lhs, cx)),
opts.display(print_term(rhs, cx)),
)
}
}
})
@ -229,92 +232,91 @@ pub(crate) fn print_where_clause(
}))
}
impl clean::Lifetime {
pub(crate) fn print(&self) -> impl Display {
self.0.as_str()
}
#[inline]
pub(crate) fn print_lifetime(lt: &clean::Lifetime) -> &str {
lt.0.as_str()
}
impl clean::ConstantKind {
pub(crate) fn print(&self, tcx: TyCtxt<'_>) -> impl Display {
let expr = self.expr(tcx);
fmt::from_fn(move |f| {
pub(crate) fn print_constant_kind(
constant_kind: &clean::ConstantKind,
tcx: TyCtxt<'_>,
) -> impl Display {
let expr = constant_kind.expr(tcx);
fmt::from_fn(
move |f| {
if f.alternate() { f.write_str(&expr) } else { write!(f, "{}", Escape(&expr)) }
})
}
},
)
}
impl clean::PolyTrait {
fn print(&self, cx: &Context<'_>) -> impl Display {
fmt::from_fn(move |f| {
print_higher_ranked_params_with_space(&self.generic_params, cx, "for").fmt(f)?;
self.trait_.print(cx).fmt(f)
})
}
fn print_poly_trait(poly_trait: &clean::PolyTrait, cx: &Context<'_>) -> impl Display {
fmt::from_fn(move |f| {
print_higher_ranked_params_with_space(&poly_trait.generic_params, cx, "for").fmt(f)?;
print_path(&poly_trait.trait_, cx).fmt(f)
})
}
impl clean::GenericBound {
pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
fmt::from_fn(move |f| match self {
clean::GenericBound::Outlives(lt) => write!(f, "{}", lt.print()),
clean::GenericBound::TraitBound(ty, modifiers) => {
// `const` and `[const]` trait bounds are experimental; don't render them.
let hir::TraitBoundModifiers { polarity, constness: _ } = modifiers;
f.write_str(match polarity {
hir::BoundPolarity::Positive => "",
hir::BoundPolarity::Maybe(_) => "?",
hir::BoundPolarity::Negative(_) => "!",
})?;
ty.print(cx).fmt(f)
}
clean::GenericBound::Use(args) => {
f.write_str("use")?;
Wrapped::with_angle_brackets()
.wrap_fn(|f| args.iter().map(|arg| arg.name()).joined(", ", f))
.fmt(f)
}
})
}
pub(crate) fn print_generic_bound(
generic_bound: &clean::GenericBound,
cx: &Context<'_>,
) -> impl Display {
fmt::from_fn(move |f| match generic_bound {
clean::GenericBound::Outlives(lt) => f.write_str(print_lifetime(lt)),
clean::GenericBound::TraitBound(ty, modifiers) => {
// `const` and `[const]` trait bounds are experimental; don't render them.
let hir::TraitBoundModifiers { polarity, constness: _ } = modifiers;
f.write_str(match polarity {
hir::BoundPolarity::Positive => "",
hir::BoundPolarity::Maybe(_) => "?",
hir::BoundPolarity::Negative(_) => "!",
})?;
print_poly_trait(ty, cx).fmt(f)
}
clean::GenericBound::Use(args) => {
f.write_str("use")?;
Wrapped::with_angle_brackets()
.wrap_fn(|f| args.iter().map(|arg| arg.name()).joined(", ", f))
.fmt(f)
}
})
}
impl clean::GenericArgs {
fn print(&self, cx: &Context<'_>) -> impl Display {
fmt::from_fn(move |f| {
match self {
clean::GenericArgs::AngleBracketed { args, constraints } => {
if !args.is_empty() || !constraints.is_empty() {
Wrapped::with_angle_brackets()
.wrap_fn(|f| {
[Either::Left(args), Either::Right(constraints)]
.into_iter()
.flat_map(Either::factor_into_iter)
.map(|either| {
either.map_either(
|arg| arg.print(cx),
|constraint| constraint.print(cx),
)
})
.joined(", ", f)
})
.fmt(f)?;
}
}
clean::GenericArgs::Parenthesized { inputs, output } => {
Wrapped::with_parens()
.wrap_fn(|f| inputs.iter().map(|ty| ty.print(cx)).joined(", ", f))
fn print_generic_args(generic_args: &clean::GenericArgs, cx: &Context<'_>) -> impl Display {
fmt::from_fn(move |f| {
match generic_args {
clean::GenericArgs::AngleBracketed { args, constraints } => {
if !args.is_empty() || !constraints.is_empty() {
Wrapped::with_angle_brackets()
.wrap_fn(|f| {
[Either::Left(args), Either::Right(constraints)]
.into_iter()
.flat_map(Either::factor_into_iter)
.map(|either| {
either.map_either(
|arg| print_generic_arg(arg, cx),
|constraint| print_assoc_item_constraint(constraint, cx),
)
})
.joined(", ", f)
})
.fmt(f)?;
if let Some(ref ty) = *output {
f.write_str(if f.alternate() { " -> " } else { " -&gt; " })?;
ty.print(cx).fmt(f)?;
}
}
clean::GenericArgs::ReturnTypeNotation => {
f.write_str("(..)")?;
}
}
Ok(())
})
}
clean::GenericArgs::Parenthesized { inputs, output } => {
Wrapped::with_parens()
.wrap_fn(|f| inputs.iter().map(|ty| print_type(ty, cx)).joined(", ", f))
.fmt(f)?;
if let Some(ref ty) = *output {
f.write_str(if f.alternate() { " -> " } else { " -&gt; " })?;
print_type(ty, cx).fmt(f)?;
}
}
clean::GenericArgs::ReturnTypeNotation => {
f.write_str("(..)")?;
}
}
Ok(())
})
}
// Possible errors when computing href link source for a `DefId`
@ -684,7 +686,7 @@ fn resolved_path(
}
}
if w.alternate() {
write!(w, "{}{:#}", last.name, last.args.print(cx))?;
write!(w, "{}{:#}", last.name, print_generic_args(&last.args, cx))?;
} else {
let path = fmt::from_fn(|f| {
if use_absolute {
@ -702,7 +704,7 @@ fn resolved_path(
write!(f, "{}", print_anchor(did, last.name, cx))
}
});
write!(w, "{path}{args}", args = last.args.print(cx))?;
write!(w, "{path}{args}", args = print_generic_args(&last.args, cx))?;
}
Ok(())
}
@ -791,11 +793,11 @@ fn print_tybounds(
cx: &Context<'_>,
) -> impl Display {
fmt::from_fn(move |f| {
bounds.iter().map(|bound| bound.print(cx)).joined(" + ", f)?;
bounds.iter().map(|bound| print_poly_trait(bound, cx)).joined(" + ", f)?;
if let Some(lt) = lt {
// We don't need to check `alternate` since we can be certain that
// the lifetime doesn't contain any characters which need escaping.
write!(f, " + {}", lt.print())?;
write!(f, " + {}", print_lifetime(lt))?;
}
Ok(())
})
@ -810,7 +812,9 @@ fn print_higher_ranked_params_with_space(
if !params.is_empty() {
f.write_str(keyword)?;
Wrapped::with_angle_brackets()
.wrap_fn(|f| params.iter().map(|lt| lt.print(cx)).joined(", ", f))
.wrap_fn(|f| {
params.iter().map(|lt| print_generic_param_def(lt, cx)).joined(", ", f)
})
.fmt(f)?;
f.write_char(' ')?;
}
@ -868,11 +872,11 @@ fn fmt_type(
} else {
primitive_link(f, PrimitiveType::Fn, format_args!("fn"), cx)?;
}
decl.decl.print(cx).fmt(f)
print_fn_decl(&decl.decl, cx).fmt(f)
}
clean::UnsafeBinder(binder) => {
print_higher_ranked_params_with_space(&binder.generic_params, cx, "unsafe").fmt(f)?;
binder.ty.print(cx).fmt(f)
print_type(&binder.ty, cx).fmt(f)
}
clean::Tuple(typs) => match &typs[..] {
&[] => primitive_link(f, PrimitiveType::Unit, format_args!("()"), cx),
@ -881,7 +885,7 @@ fn fmt_type(
primitive_link(f, PrimitiveType::Tuple, format_args!("({name},)"), cx)
} else {
write!(f, "(")?;
one.print(cx).fmt(f)?;
print_type(one, cx).fmt(f)?;
write!(f, ",)")
}
}
@ -907,7 +911,7 @@ fn fmt_type(
)
} else {
Wrapped::with_parens()
.wrap_fn(|f| many.iter().map(|item| item.print(cx)).joined(", ", f))
.wrap_fn(|f| many.iter().map(|item| print_type(item, cx)).joined(", ", f))
.fmt(f)
}
}
@ -915,9 +919,9 @@ fn fmt_type(
clean::Slice(box clean::Generic(name)) => {
primitive_link(f, PrimitiveType::Slice, format_args!("[{name}]"), cx)
}
clean::Slice(t) => Wrapped::with_square_brackets().wrap(t.print(cx)).fmt(f),
clean::Slice(t) => Wrapped::with_square_brackets().wrap(print_type(t, cx)).fmt(f),
clean::Type::Pat(t, pat) => {
fmt::Display::fmt(&t.print(cx), f)?;
fmt::Display::fmt(&print_type(t, cx), f)?;
write!(f, " is {pat}")
}
clean::Array(box clean::Generic(name), n) if !f.alternate() => primitive_link(
@ -928,7 +932,7 @@ fn fmt_type(
),
clean::Array(t, n) => Wrapped::with_square_brackets()
.wrap(fmt::from_fn(|f| {
t.print(cx).fmt(f)?;
print_type(t, cx).fmt(f)?;
f.write_str("; ")?;
if f.alternate() {
f.write_str(n)
@ -944,17 +948,17 @@ fn fmt_type(
primitive_link(
f,
clean::PrimitiveType::RawPointer,
format_args!("*{m} {ty}", ty = WithOpts::from(f).display(t.print(cx))),
format_args!("*{m} {ty}", ty = WithOpts::from(f).display(print_type(t, cx))),
cx,
)
} else {
primitive_link(f, clean::PrimitiveType::RawPointer, format_args!("*{m} "), cx)?;
t.print(cx).fmt(f)
print_type(t, cx).fmt(f)
}
}
clean::BorrowedRef { lifetime: l, mutability, type_: ty } => {
let lt = fmt::from_fn(|f| match l {
Some(l) => write!(f, "{} ", l.print()),
Some(l) => write!(f, "{} ", print_lifetime(l)),
_ => Ok(()),
});
let m = mutability.print_with_space();
@ -989,133 +993,133 @@ fn fmt_type(
f.write_str("impl ")?;
print_generic_bounds(bounds, cx).fmt(f)
}
clean::QPath(qpath) => qpath.print(cx).fmt(f),
clean::QPath(qpath) => print_qpath_data(qpath, cx).fmt(f),
}
}
impl clean::Type {
pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
fmt::from_fn(move |f| fmt_type(self, f, false, cx))
}
pub(crate) fn print_type(type_: &clean::Type, cx: &Context<'_>) -> impl Display {
fmt::from_fn(move |f| fmt_type(type_, f, false, cx))
}
impl clean::Path {
pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
fmt::from_fn(move |f| resolved_path(f, self.def_id(), self, false, false, cx))
}
pub(crate) fn print_path(path: &clean::Path, cx: &Context<'_>) -> impl Display {
fmt::from_fn(move |f| resolved_path(f, path.def_id(), path, false, false, cx))
}
impl clean::QPathData {
fn print(&self, cx: &Context<'_>) -> impl Display {
let Self { ref assoc, ref self_type, should_fully_qualify, ref trait_ } = *self;
fn print_qpath_data(qpath_data: &clean::QPathData, cx: &Context<'_>) -> impl Display {
let clean::QPathData { ref assoc, ref self_type, should_fully_qualify, ref trait_ } =
*qpath_data;
fmt::from_fn(move |f| {
// FIXME(inherent_associated_types): Once we support non-ADT self-types (#106719),
// we need to surround them with angle brackets in some cases (e.g. `<dyn …>::P`).
fmt::from_fn(move |f| {
// FIXME(inherent_associated_types): Once we support non-ADT self-types (#106719),
// we need to surround them with angle brackets in some cases (e.g. `<dyn …>::P`).
if let Some(trait_) = trait_
&& should_fully_qualify
{
let opts = WithOpts::from(f);
Wrapped::with_angle_brackets()
.wrap(format_args!(
"{} as {}",
opts.display(self_type.print(cx)),
opts.display(trait_.print(cx))
))
.fmt(f)?
} else {
self_type.print(cx).fmt(f)?;
}
f.write_str("::")?;
// It's pretty unsightly to look at `<A as B>::C` in output, and
// we've got hyperlinking on our side, so try to avoid longer
// notation as much as possible by making `C` a hyperlink to trait
// `B` to disambiguate.
//
// FIXME: this is still a lossy conversion and there should probably
// be a better way of representing this in general? Most of
// the ugliness comes from inlining across crates where
// everything comes in as a fully resolved QPath (hard to
// look at).
if !f.alternate() {
// FIXME(inherent_associated_types): We always link to the very first associated
// type (in respect to source order) that bears the given name (`assoc.name`) and that is
// affiliated with the computed `DefId`. This is obviously incorrect when we have
// multiple impl blocks. Ideally, we would thread the `DefId` of the assoc ty itself
// through here and map it to the corresponding HTML ID that was generated by
// `render::Context::derive_id` when the impl blocks were rendered.
// There is no such mapping unfortunately.
// As a hack, we could badly imitate `derive_id` here by keeping *count* when looking
// for the assoc ty `DefId` in `tcx.associated_items(self_ty_did).in_definition_order()`
// considering privacy, `doc(hidden)`, etc.
// I don't feel like that right now :cold_sweat:.
if let Some(trait_) = trait_
&& should_fully_qualify
{
let opts = WithOpts::from(f);
Wrapped::with_angle_brackets()
.wrap(format_args!(
"{} as {}",
opts.display(print_type(self_type, cx)),
opts.display(print_path(trait_, cx))
))
.fmt(f)?
} else {
print_type(self_type, cx).fmt(f)?;
}
f.write_str("::")?;
// It's pretty unsightly to look at `<A as B>::C` in output, and
// we've got hyperlinking on our side, so try to avoid longer
// notation as much as possible by making `C` a hyperlink to trait
// `B` to disambiguate.
//
// FIXME: this is still a lossy conversion and there should probably
// be a better way of representing this in general? Most of
// the ugliness comes from inlining across crates where
// everything comes in as a fully resolved QPath (hard to
// look at).
if !f.alternate() {
// FIXME(inherent_associated_types): We always link to the very first associated
// type (in respect to source order) that bears the given name (`assoc.name`) and that is
// affiliated with the computed `DefId`. This is obviously incorrect when we have
// multiple impl blocks. Ideally, we would thread the `DefId` of the assoc ty itself
// through here and map it to the corresponding HTML ID that was generated by
// `render::Context::derive_id` when the impl blocks were rendered.
// There is no such mapping unfortunately.
// As a hack, we could badly imitate `derive_id` here by keeping *count* when looking
// for the assoc ty `DefId` in `tcx.associated_items(self_ty_did).in_definition_order()`
// considering privacy, `doc(hidden)`, etc.
// I don't feel like that right now :cold_sweat:.
let parent_href = match trait_ {
Some(trait_) => href(trait_.def_id(), cx).ok(),
None => self_type.def_id(cx.cache()).and_then(|did| href(did, cx).ok()),
};
let parent_href = match trait_ {
Some(trait_) => href(trait_.def_id(), cx).ok(),
None => self_type.def_id(cx.cache()).and_then(|did| href(did, cx).ok()),
};
if let Some((url, _, path)) = parent_href {
write!(
f,
"<a class=\"associatedtype\" href=\"{url}#{shortty}.{name}\" \
title=\"type {path}::{name}\">{name}</a>",
shortty = ItemType::AssocType,
name = assoc.name,
path = join_path_syms(path),
)
} else {
write!(f, "{}", assoc.name)
}
if let Some((url, _, path)) = parent_href {
write!(
f,
"<a class=\"associatedtype\" href=\"{url}#{shortty}.{name}\" \
title=\"type {path}::{name}\">{name}</a>",
shortty = ItemType::AssocType,
name = assoc.name,
path = join_path_syms(path),
)
} else {
write!(f, "{}", assoc.name)
}?;
}
} else {
write!(f, "{}", assoc.name)
}?;
assoc.args.print(cx).fmt(f)
})
}
print_generic_args(&assoc.args, cx).fmt(f)
})
}
pub(crate) fn print_impl(
impl_: &clean::Impl,
use_absolute: bool,
cx: &Context<'_>,
) -> impl Display {
fmt::from_fn(move |f| {
f.write_str("impl")?;
print_generics(&impl_.generics, cx).fmt(f)?;
f.write_str(" ")?;
if let Some(ref ty) = impl_.trait_ {
if impl_.is_negative_trait_impl() {
f.write_char('!')?;
}
if impl_.kind.is_fake_variadic()
&& let Some(generics) = ty.generics()
&& let Ok(inner_type) = generics.exactly_one()
{
let last = ty.last();
if f.alternate() {
write!(f, "{last}")?;
} else {
write!(f, "{}", print_anchor(ty.def_id(), last, cx))?;
};
Wrapped::with_angle_brackets()
.wrap_fn(|f| impl_.print_type(inner_type, f, use_absolute, cx))
.fmt(f)?;
} else {
print_path(ty, cx).fmt(f)?;
}
f.write_str(" for ")?;
}
if let Some(ty) = impl_.kind.as_blanket_ty() {
fmt_type(ty, f, use_absolute, cx)?;
} else {
impl_.print_type(&impl_.for_, f, use_absolute, cx)?;
}
print_where_clause(&impl_.generics, cx, 0, Ending::Newline).maybe_display().fmt(f)
})
}
impl clean::Impl {
pub(crate) fn print(&self, use_absolute: bool, cx: &Context<'_>) -> impl Display {
fmt::from_fn(move |f| {
f.write_str("impl")?;
self.generics.print(cx).fmt(f)?;
f.write_str(" ")?;
if let Some(ref ty) = self.trait_ {
if self.is_negative_trait_impl() {
f.write_char('!')?;
}
if self.kind.is_fake_variadic()
&& let Some(generics) = ty.generics()
&& let Ok(inner_type) = generics.exactly_one()
{
let last = ty.last();
if f.alternate() {
write!(f, "{last}")?;
} else {
write!(f, "{}", print_anchor(ty.def_id(), last, cx))?;
};
Wrapped::with_angle_brackets()
.wrap_fn(|f| self.print_type(inner_type, f, use_absolute, cx))
.fmt(f)?;
} else {
ty.print(cx).fmt(f)?;
}
f.write_str(" for ")?;
}
if let Some(ty) = self.kind.as_blanket_ty() {
fmt_type(ty, f, use_absolute, cx)?;
} else {
self.print_type(&self.for_, f, use_absolute, cx)?;
}
print_where_clause(&self.generics, cx, 0, Ending::Newline).maybe_display().fmt(f)
})
}
fn print_type(
&self,
type_: &clean::Type,
@ -1191,7 +1195,7 @@ pub(crate) fn print_params(params: &[clean::Parameter], cx: &Context<'_>) -> imp
if let Some(name) = param.name {
write!(f, "{name}: ")?;
}
param.type_.print(cx).fmt(f)
print_type(&param.type_, cx).fmt(f)
})
})
.joined(", ", f)
@ -1221,76 +1225,73 @@ impl Display for Indent {
}
}
impl clean::Parameter {
fn print(&self, cx: &Context<'_>) -> impl fmt::Display {
fmt::from_fn(move |f| {
if let Some(self_ty) = self.to_receiver() {
match self_ty {
clean::SelfTy => f.write_str("self"),
clean::BorrowedRef { lifetime, mutability, type_: box clean::SelfTy } => {
f.write_str(if f.alternate() { "&" } else { "&amp;" })?;
if let Some(lt) = lifetime {
write!(f, "{lt} ", lt = lt.print())?;
}
write!(f, "{mutability}self", mutability = mutability.print_with_space())
}
_ => {
f.write_str("self: ")?;
self_ty.print(cx).fmt(f)
fn print_parameter(parameter: &clean::Parameter, cx: &Context<'_>) -> impl fmt::Display {
fmt::from_fn(move |f| {
if let Some(self_ty) = parameter.to_receiver() {
match self_ty {
clean::SelfTy => f.write_str("self"),
clean::BorrowedRef { lifetime, mutability, type_: box clean::SelfTy } => {
f.write_str(if f.alternate() { "&" } else { "&amp;" })?;
if let Some(lt) = lifetime {
write!(f, "{lt} ", lt = print_lifetime(lt))?;
}
write!(f, "{mutability}self", mutability = mutability.print_with_space())
}
} else {
if self.is_const {
write!(f, "const ")?;
_ => {
f.write_str("self: ")?;
print_type(self_ty, cx).fmt(f)
}
if let Some(name) = self.name {
write!(f, "{name}: ")?;
}
self.type_.print(cx).fmt(f)
}
})
}
} else {
if parameter.is_const {
write!(f, "const ")?;
}
if let Some(name) = parameter.name {
write!(f, "{name}: ")?;
}
print_type(&parameter.type_, cx).fmt(f)
}
})
}
fn print_fn_decl(fn_decl: &clean::FnDecl, cx: &Context<'_>) -> impl Display {
fmt::from_fn(move |f| {
let ellipsis = if fn_decl.c_variadic { ", ..." } else { "" };
Wrapped::with_parens()
.wrap_fn(|f| {
print_params(&fn_decl.inputs, cx).fmt(f)?;
f.write_str(ellipsis)
})
.fmt(f)?;
fn_decl.print_output(cx).fmt(f)
})
}
/// * `header_len`: The length of the function header and name. In other words, the number of
/// characters in the function declaration up to but not including the parentheses.
/// This is expected to go into a `<pre>`/`code-header` block, so indentation and newlines
/// are preserved.
/// * `indent`: The number of spaces to indent each successive line with, if line-wrapping is
/// necessary.
pub(crate) fn full_print_fn_decl(
fn_decl: &clean::FnDecl,
header_len: usize,
indent: usize,
cx: &Context<'_>,
) -> impl Display {
fmt::from_fn(move |f| {
// First, generate the text form of the declaration, with no line wrapping, and count the bytes.
let mut counter = WriteCounter(0);
write!(&mut counter, "{:#}", fmt::from_fn(|f| { fn_decl.inner_full_print(None, f, cx) }))?;
// If the text form was over 80 characters wide, we will line-wrap our output.
let line_wrapping_indent = if header_len + counter.0 > 80 { Some(indent) } else { None };
// Generate the final output. This happens to accept `{:#}` formatting to get textual
// output but in practice it is only formatted with `{}` to get HTML output.
fn_decl.inner_full_print(line_wrapping_indent, f, cx)
})
}
impl clean::FnDecl {
pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
fmt::from_fn(move |f| {
let ellipsis = if self.c_variadic { ", ..." } else { "" };
Wrapped::with_parens()
.wrap_fn(|f| {
print_params(&self.inputs, cx).fmt(f)?;
f.write_str(ellipsis)
})
.fmt(f)?;
self.print_output(cx).fmt(f)
})
}
/// * `header_len`: The length of the function header and name. In other words, the number of
/// characters in the function declaration up to but not including the parentheses.
/// This is expected to go into a `<pre>`/`code-header` block, so indentation and newlines
/// are preserved.
/// * `indent`: The number of spaces to indent each successive line with, if line-wrapping is
/// necessary.
pub(crate) fn full_print(
&self,
header_len: usize,
indent: usize,
cx: &Context<'_>,
) -> impl Display {
fmt::from_fn(move |f| {
// First, generate the text form of the declaration, with no line wrapping, and count the bytes.
let mut counter = WriteCounter(0);
write!(&mut counter, "{:#}", fmt::from_fn(|f| { self.inner_full_print(None, f, cx) }))?;
// If the text form was over 80 characters wide, we will line-wrap our output.
let line_wrapping_indent =
if header_len + counter.0 > 80 { Some(indent) } else { None };
// Generate the final output. This happens to accept `{:#}` formatting to get textual
// output but in practice it is only formatted with `{}` to get HTML output.
self.inner_full_print(line_wrapping_indent, f, cx)
})
}
fn inner_full_print(
&self,
// For None, the declaration will not be line-wrapped. For Some(n),
@ -1316,7 +1317,7 @@ impl clean::FnDecl {
}
});
self.inputs.iter().map(|param| param.print(cx)).joined(sep, f)?;
self.inputs.iter().map(|param| print_parameter(param, cx)).joined(sep, f)?;
if line_wrapping_indent.is_some() {
writeln!(f, ",")?
@ -1348,7 +1349,7 @@ impl clean::FnDecl {
}
f.write_str(if f.alternate() { " -> " } else { " -&gt; " })?;
self.output.print(cx).fmt(f)
print_type(&self.output, cx).fmt(f)
})
}
}
@ -1461,67 +1462,68 @@ pub(crate) fn print_constness_with_space(
}
}
impl clean::Import {
pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
fmt::from_fn(move |f| match self.kind {
clean::ImportKind::Simple(name) => {
if name == self.source.path.last() {
write!(f, "use {};", self.source.print(cx))
} else {
write!(f, "use {source} as {name};", source = self.source.print(cx))
}
pub(crate) fn print_import(import: &clean::Import, cx: &Context<'_>) -> impl Display {
fmt::from_fn(move |f| match import.kind {
clean::ImportKind::Simple(name) => {
if name == import.source.path.last() {
write!(f, "use {};", print_import_source(&import.source, cx))
} else {
write!(
f,
"use {source} as {name};",
source = print_import_source(&import.source, cx)
)
}
clean::ImportKind::Glob => {
if self.source.path.segments.is_empty() {
write!(f, "use *;")
} else {
write!(f, "use {}::*;", self.source.print(cx))
}
}
clean::ImportKind::Glob => {
if import.source.path.segments.is_empty() {
write!(f, "use *;")
} else {
write!(f, "use {}::*;", print_import_source(&import.source, cx))
}
})
}
}
})
}
impl clean::ImportSource {
pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
fmt::from_fn(move |f| match self.did {
Some(did) => resolved_path(f, did, &self.path, true, false, cx),
_ => {
for seg in &self.path.segments[..self.path.segments.len() - 1] {
write!(f, "{}::", seg.name)?;
}
let name = self.path.last();
if let hir::def::Res::PrimTy(p) = self.path.res {
primitive_link(f, PrimitiveType::from(p), format_args!("{name}"), cx)?;
} else {
f.write_str(name.as_str())?;
}
Ok(())
fn print_import_source(import_source: &clean::ImportSource, cx: &Context<'_>) -> impl Display {
fmt::from_fn(move |f| match import_source.did {
Some(did) => resolved_path(f, did, &import_source.path, true, false, cx),
_ => {
for seg in &import_source.path.segments[..import_source.path.segments.len() - 1] {
write!(f, "{}::", seg.name)?;
}
})
}
}
impl clean::AssocItemConstraint {
pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
fmt::from_fn(move |f| {
f.write_str(self.assoc.name.as_str())?;
self.assoc.args.print(cx).fmt(f)?;
match self.kind {
clean::AssocItemConstraintKind::Equality { ref term } => {
f.write_str(" = ")?;
term.print(cx).fmt(f)?;
}
clean::AssocItemConstraintKind::Bound { ref bounds } => {
if !bounds.is_empty() {
f.write_str(": ")?;
print_generic_bounds(bounds, cx).fmt(f)?;
}
}
let name = import_source.path.last();
if let hir::def::Res::PrimTy(p) = import_source.path.res {
primitive_link(f, PrimitiveType::from(p), format_args!("{name}"), cx)?;
} else {
f.write_str(name.as_str())?;
}
Ok(())
})
}
}
})
}
fn print_assoc_item_constraint(
assoc_item_constraint: &clean::AssocItemConstraint,
cx: &Context<'_>,
) -> impl Display {
fmt::from_fn(move |f| {
f.write_str(assoc_item_constraint.assoc.name.as_str())?;
print_generic_args(&assoc_item_constraint.assoc.args, cx).fmt(f)?;
match assoc_item_constraint.kind {
clean::AssocItemConstraintKind::Equality { ref term } => {
f.write_str(" = ")?;
print_term(term, cx).fmt(f)?;
}
clean::AssocItemConstraintKind::Bound { ref bounds } => {
if !bounds.is_empty() {
f.write_str(": ")?;
print_generic_bounds(bounds, cx).fmt(f)?;
}
}
}
Ok(())
})
}
pub(crate) fn print_abi_with_space(abi: ExternAbi) -> impl Display {
@ -1538,22 +1540,18 @@ pub(crate) fn print_default_space(v: bool) -> &'static str {
if v { "default " } else { "" }
}
impl clean::GenericArg {
pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
fmt::from_fn(move |f| match self {
clean::GenericArg::Lifetime(lt) => lt.print().fmt(f),
clean::GenericArg::Type(ty) => ty.print(cx).fmt(f),
clean::GenericArg::Const(ct) => ct.print(cx.tcx()).fmt(f),
clean::GenericArg::Infer => Display::fmt("_", f),
})
}
fn print_generic_arg(generic_arg: &clean::GenericArg, cx: &Context<'_>) -> impl Display {
fmt::from_fn(move |f| match generic_arg {
clean::GenericArg::Lifetime(lt) => f.write_str(print_lifetime(lt)),
clean::GenericArg::Type(ty) => print_type(ty, cx).fmt(f),
clean::GenericArg::Const(ct) => print_constant_kind(ct, cx.tcx()).fmt(f),
clean::GenericArg::Infer => f.write_char('_'),
})
}
impl clean::Term {
pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
fmt::from_fn(move |f| match self {
clean::Term::Type(ty) => ty.print(cx).fmt(f),
clean::Term::Constant(ct) => ct.print(cx.tcx()).fmt(f),
})
}
fn print_term(term: &clean::Term, cx: &Context<'_>) -> impl Display {
fmt::from_fn(move |f| match term {
clean::Term::Type(ty) => print_type(ty, cx).fmt(f),
clean::Term::Constant(ct) => print_constant_kind(ct, cx.tcx()).fmt(f),
})
}

View file

@ -74,8 +74,9 @@ use crate::formats::cache::Cache;
use crate::formats::item_type::ItemType;
use crate::html::escape::Escape;
use crate::html::format::{
Ending, HrefError, PrintWithSpace, href, print_abi_with_space, print_constness_with_space,
print_default_space, print_generic_bounds, print_where_clause, visibility_print_with_space,
Ending, HrefError, PrintWithSpace, full_print_fn_decl, href, print_abi_with_space,
print_constness_with_space, print_default_space, print_generic_bounds, print_generics,
print_impl, print_path, print_type, print_where_clause, visibility_print_with_space,
};
use crate::html::markdown::{
HeadingOffset, IdMap, Markdown, MarkdownItemInfo, MarkdownSummaryLine,
@ -1044,8 +1045,8 @@ fn assoc_const(
vis = visibility_print_with_space(it, cx),
href = assoc_href_attr(it, link, cx).maybe_display(),
name = it.name.as_ref().unwrap(),
generics = generics.print(cx),
ty = ty.print(cx),
generics = print_generics(generics, cx),
ty = print_type(ty, cx),
)?;
if let AssocConstValue::TraitDefault(konst) | AssocConstValue::Impl(konst) = value {
// FIXME: `.value()` uses `clean::utils::format_integer_with_underscore_sep` under the
@ -1083,14 +1084,14 @@ fn assoc_type(
vis = visibility_print_with_space(it, cx),
href = assoc_href_attr(it, link, cx).maybe_display(),
name = it.name.as_ref().unwrap(),
generics = generics.print(cx),
generics = print_generics(generics, cx),
)?;
if !bounds.is_empty() {
write!(w, ": {}", print_generic_bounds(bounds, cx))?;
}
// Render the default before the where-clause which aligns with the new recommended style. See #89122.
if let Some(default) = default {
write!(w, " = {}", default.print(cx))?;
write!(w, " = {}", print_type(default, cx))?;
}
write!(w, "{}", print_where_clause(generics, cx, indent, Ending::NoNewline).maybe_display())
})
@ -1128,7 +1129,7 @@ fn assoc_method(
let href = assoc_href_attr(meth, link, cx).maybe_display();
// NOTE: `{:#}` does not print HTML formatting, `{}` does. So `g.print` can't be reused between the length calculation and `write!`.
let generics_len = format!("{:#}", g.print(cx)).len();
let generics_len = format!("{:#}", print_generics(g, cx)).len();
let mut header_len = "fn ".len()
+ vis.len()
+ defaultness.len()
@ -1155,8 +1156,8 @@ fn assoc_method(
"{indent}{vis}{defaultness}{constness}{asyncness}{safety}{abi}fn \
<a{href} class=\"fn\">{name}</a>{generics}{decl}{notable_traits}{where_clause}",
indent = indent_str,
generics = g.print(cx),
decl = d.full_print(header_len, indent, cx),
generics = print_generics(g, cx),
decl = full_print_fn_decl(d, header_len, indent, cx),
where_clause = print_where_clause(g, cx, indent, end_newline).maybe_display(),
)
})
@ -1441,8 +1442,10 @@ fn render_assoc_items_inner(
Cow::Borrowed("implementations-list"),
),
AssocItemRender::DerefFor { trait_, type_, .. } => {
let id =
cx.derive_id(small_url_encode(format!("deref-methods-{:#}", type_.print(cx))));
let id = cx.derive_id(small_url_encode(format!(
"deref-methods-{:#}",
print_type(type_, cx)
)));
// the `impls.get` above only looks at the outermost type,
// and the Deref impl may only be implemented for certain
// values of generic parameters.
@ -1466,8 +1469,8 @@ fn render_assoc_items_inner(
fmt::from_fn(|f| write!(
f,
"<span>Methods from {trait_}&lt;Target = {type_}&gt;</span>",
trait_ = trait_.print(cx),
type_ = type_.print(cx),
trait_ = print_path(trait_, cx),
type_ = print_type(type_, cx),
)),
&id,
)
@ -1645,7 +1648,7 @@ fn notable_traits_button(ty: &clean::Type, cx: &Context<'_>) -> Option<impl fmt:
write!(
f,
" <a href=\"#\" class=\"tooltip\" data-notable-ty=\"{ty}\">ⓘ</a>",
ty = Escape(&format!("{:#}", ty.print(cx))),
ty = Escape(&format!("{:#}", print_type(ty, cx))),
)
})
})
@ -1683,7 +1686,7 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) {
f,
"<h3>Notable traits for <code>{}</code></h3>\
<pre><code>",
impl_.for_.print(cx)
print_type(&impl_.for_, cx),
)?;
true
} else {
@ -1691,7 +1694,7 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) {
};
for (impl_, trait_did) in notable_impls {
write!(f, "<div class=\"where\">{}</div>", impl_.print(false, cx))?;
write!(f, "<div class=\"where\">{}</div>", print_impl(impl_, false, cx))?;
for it in &impl_.items {
let clean::AssocTypeItem(tydef, ..) = &it.kind else {
continue;
@ -1724,7 +1727,7 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) {
})
.to_string();
(format!("{:#}", ty.print(cx)), out)
(format!("{:#}", print_type(ty, cx)), out)
}
fn notable_traits_json<'a>(tys: impl Iterator<Item = &'a clean::Type>, cx: &Context<'_>) -> String {
@ -2284,7 +2287,7 @@ fn render_impl_summary(
)?;
if let Some(use_absolute) = use_absolute {
write!(w, "{}", inner_impl.print(use_absolute, cx))?;
write!(w, "{}", print_impl(inner_impl, use_absolute, cx))?;
if show_def_docs {
for it in &inner_impl.items {
if let clean::AssocTypeItem(ref tydef, ref _bounds) = it.kind {
@ -2305,7 +2308,7 @@ fn render_impl_summary(
}
}
} else {
write!(w, "{}", inner_impl.print(false, cx))?;
write!(w, "{}", print_impl(inner_impl, false, cx))?;
}
w.write_str("</h3>")?;
@ -2423,7 +2426,10 @@ fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String
clean::ItemKind::ImplItem(ref i) if i.trait_.is_some() => {
// Alternative format produces no URLs,
// so this parameter does nothing.
Some((format!("{:#}", i.for_.print(cx)), get_id_for_impl(cx.tcx(), item.item_id)))
Some((
format!("{:#}", print_type(&i.for_, cx)),
get_id_for_impl(cx.tcx(), item.item_id),
))
}
_ => None,
}

View file

@ -31,7 +31,8 @@ use crate::formats::Impl;
use crate::formats::item_type::ItemType;
use crate::html::escape::{Escape, EscapeBodyTextWithWbr};
use crate::html::format::{
Ending, PrintWithSpace, print_abi_with_space, print_constness_with_space, print_where_clause,
Ending, PrintWithSpace, full_print_fn_decl, print_abi_with_space, print_constness_with_space,
print_generic_bound, print_generics, print_impl, print_import, print_type, print_where_clause,
visibility_print_with_space,
};
use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine};
@ -462,7 +463,7 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
"{vis}{imp}</code>{stab_tags}\
</dt>",
vis = visibility_print_with_space(myitem, cx),
imp = import.print(cx)
imp = print_import(import, cx),
)?;
}
_ => {
@ -611,7 +612,7 @@ fn item_function(cx: &Context<'_>, it: &clean::Item, f: &clean::Function) -> imp
let visibility = visibility_print_with_space(it, cx).to_string();
let name = it.name.unwrap();
let generics_len = format!("{:#}", f.generics.print(cx)).len();
let generics_len = format!("{:#}", print_generics(&f.generics, cx)).len();
let header_len = "fn ".len()
+ visibility.len()
+ constness.len()
@ -635,10 +636,10 @@ fn item_function(cx: &Context<'_>, it: &clean::Item, f: &clean::Function) -> imp
safety = safety,
abi = abi,
name = name,
generics = f.generics.print(cx),
generics = print_generics(&f.generics, cx),
where_clause =
print_where_clause(&f.generics, cx, 0, Ending::Newline).maybe_display(),
decl = f.decl.full_print(header_len, 0, cx),
decl = full_print_fn_decl(&f.decl, header_len, 0, cx),
)
})?;
write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
@ -673,7 +674,7 @@ fn item_trait(cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) -> impl fmt:
safety = t.safety(tcx).print_with_space(),
is_auto = if t.is_auto(tcx) { "auto " } else { "" },
name = it.name.unwrap(),
generics = t.generics.print(cx),
generics = print_generics(&t.generics, cx),
)?;
if !t.generics.where_predicates.is_empty() {
@ -1244,7 +1245,7 @@ fn item_trait_alias(
w,
"trait {name}{generics} = {bounds}{where_clause};",
name = it.name.unwrap(),
generics = t.generics.print(cx),
generics = print_generics(&t.generics, cx),
bounds = print_bounds(&t.bounds, true, cx),
where_clause =
print_where_clause(&t.generics, cx, 0, Ending::NoNewline).maybe_display(),
@ -1273,10 +1274,10 @@ fn item_type_alias(cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) ->
"{vis}type {name}{generics}{where_clause} = {type_};",
vis = visibility_print_with_space(it, cx),
name = it.name.unwrap(),
generics = t.generics.print(cx),
generics = print_generics(&t.generics, cx),
where_clause =
print_where_clause(&t.generics, cx, 0, Ending::Newline).maybe_display(),
type_ = t.type_.print(cx),
type_ = print_type(&t.type_, cx),
)
})?;
@ -1477,7 +1478,7 @@ impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
}
fn print_ty(&self, ty: &'a clean::Type) -> impl Display {
ty.print(self.cx)
print_type(ty, self.cx)
}
// FIXME (GuillaumeGomez): When <https://github.com/askama-rs/askama/issues/452> is implemented,
@ -1523,7 +1524,7 @@ fn print_tuple_struct_fields(cx: &Context<'_>, s: &[clean::Item]) -> impl Displa
.map(|ty| {
fmt::from_fn(|f| match ty.kind {
clean::StrippedItem(box clean::StructFieldItem(_)) => f.write_str("_"),
clean::StructFieldItem(ref ty) => write!(f, "{}", ty.print(cx)),
clean::StructFieldItem(ref ty) => write!(f, "{}", print_type(ty, cx)),
_ => unreachable!(),
})
})
@ -1562,7 +1563,7 @@ impl<'clean> DisplayEnum<'clean> {
"{}enum {}{}{}",
visibility_print_with_space(it, cx),
it.name.unwrap(),
self.generics.print(cx),
print_generics(&self.generics, cx),
render_enum_fields(
cx,
Some(self.generics),
@ -1862,7 +1863,7 @@ fn item_variants(
{doc}\
</div>",
f = field.name.unwrap(),
t = ty.print(cx),
t = print_type(ty, cx),
doc = document(cx, field, Some(variant), HeadingOffset::H5),
)?;
}
@ -1956,8 +1957,8 @@ fn item_constant(
"{vis}const {name}{generics}: {typ}{where_clause}",
vis = visibility_print_with_space(it, cx),
name = it.name.unwrap(),
generics = generics.print(cx),
typ = ty.print(cx),
generics = print_generics(generics, cx),
typ = print_type(ty, cx),
where_clause =
print_where_clause(generics, cx, 0, Ending::NoNewline).maybe_display(),
)?;
@ -2102,7 +2103,7 @@ fn item_fields(
"{field_name}: {ty}</code>\
</span>\
{doc}",
ty = ty.print(cx),
ty = print_type(ty, cx),
doc = document(cx, field, Some(it), HeadingOffset::H3),
)?;
}
@ -2127,7 +2128,7 @@ fn item_static(
safe = safety.map(|safe| safe.prefix_str()).unwrap_or(""),
mutability = s.mutability.print_with_space(),
name = it.name.unwrap(),
typ = s.type_.print(cx)
typ = print_type(&s.type_, cx)
)
})?;
@ -2286,7 +2287,7 @@ fn print_bounds(
}
}
bounds.iter().map(|p| p.print(cx)).joined(inter_str, f)
bounds.iter().map(|p| print_generic_bound(p, cx)).joined(inter_str, f)
}))
.maybe_display()
}
@ -2307,7 +2308,7 @@ struct ImplString(String);
impl ImplString {
fn new(i: &Impl, cx: &Context<'_>) -> ImplString {
ImplString(format!("{}", i.inner_impl().print(false, cx)))
ImplString(format!("{}", print_impl(i.inner_impl(), false, cx)))
}
}
@ -2376,7 +2377,7 @@ fn render_union(
write!(f, "{}union {}", visibility_print_with_space(it, cx), it.name.unwrap(),)?;
let where_displayed = if let Some(generics) = g {
write!(f, "{}", generics.print(cx))?;
write!(f, "{}", print_generics(generics, cx))?;
if let Some(where_clause) = print_where_clause(generics, cx, 0, Ending::Newline) {
write!(f, "{where_clause}")?;
true
@ -2408,7 +2409,7 @@ fn render_union(
" {}{}: {},",
visibility_print_with_space(field, cx),
field.name.unwrap(),
ty.print(cx)
print_type(ty, cx)
)?;
}
}
@ -2442,7 +2443,7 @@ fn render_struct(
it.name.unwrap()
)?;
if let Some(g) = g {
write!(w, "{}", g.print(cx))?;
write!(w, "{}", print_generics(g, cx))?;
}
write!(
w,
@ -2505,7 +2506,7 @@ fn render_struct_fields(
"{tab} {vis}{name}: {ty},",
vis = visibility_print_with_space(field, cx),
name = field.name.unwrap(),
ty = ty.print(cx)
ty = print_type(ty, cx)
)?;
}
}
@ -2548,7 +2549,7 @@ fn render_struct_fields(
w,
"{}{}",
visibility_print_with_space(field, cx),
ty.print(cx)
print_type(ty, cx),
)?;
}
_ => unreachable!(),

View file

@ -13,6 +13,7 @@ use super::{Context, ItemSection, item_ty_to_section};
use crate::clean;
use crate::formats::Impl;
use crate::formats::item_type::ItemType;
use crate::html::format::{print_path, print_type};
use crate::html::markdown::{IdMap, MarkdownWithToc};
use crate::html::render::print_item::compare_names;
@ -558,8 +559,8 @@ fn sidebar_deref_methods<'a>(
};
let title = format!(
"Methods from {:#}<Target={:#}>",
impl_.inner_impl().trait_.as_ref().unwrap().print(cx),
real_target.print(cx),
print_path(impl_.inner_impl().trait_.as_ref().unwrap(), cx),
print_type(real_target, cx),
);
// We want links' order to be reproducible so we don't use unstable sort.
ret.sort();
@ -690,7 +691,7 @@ fn sidebar_render_assoc_items(
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
ty::ImplPolarity::Negative => "!",
};
let generated = Link::new(encoded, format!("{prefix}{:#}", trait_.print(cx)));
let generated = Link::new(encoded, format!("{prefix}{:#}", print_path(trait_, cx)));
if links.insert(generated.clone()) { Some(generated) } else { None }
})
.collect::<Vec<Link<'static>>>();

View file

@ -44,6 +44,7 @@ use crate::docfs::PathError;
use crate::error::Error;
use crate::formats::Impl;
use crate::formats::item_type::ItemType;
use crate::html::format::{print_impl, print_path};
use crate::html::layout;
use crate::html::render::ordered_json::{EscapedJson, OrderedJson};
use crate::html::render::search_index::{SerializedSearchIndex, build_index};
@ -605,7 +606,7 @@ impl TypeAliasPart {
.inner_impl()
.trait_
.as_ref()
.map(|trait_| format!("{:#}", trait_.print(cx)));
.map(|trait_| format!("{:#}", print_path(trait_, cx)));
ret = Some(AliasSerializableImpl {
text,
trait_,
@ -704,7 +705,7 @@ impl TraitAliasPart {
None
} else {
Some(Implementor {
text: imp.inner_impl().print(false, cx).to_string(),
text: print_impl(imp.inner_impl(), false, cx).to_string(),
synthetic: imp.inner_impl().kind.is_auto(),
types: collect_paths_for_type(&imp.inner_impl().for_, cache),
})