::P`).
            if f.alternate() {
                if let Some(trait_) = trait_
                    && should_fully_qualify
                {
                    write!(f, "<{:#} as {:#}>::", self_type.print(cx), trait_.print(cx))?
                } else {
                    write!(f, "{:#}::", self_type.print(cx))?
                }
            } else {
                if let Some(trait_) = trait_
                    && should_fully_qualify
                {
                    write!(f, "<{} as {}>::", self_type.print(cx), trait_.print(cx))?
                } else {
                    write!(f, "{}::", self_type.print(cx))?
                }
            };
            // It's pretty unsightly to look at `::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()),
                };
                if let Some((url, _, path)) = parent_href {
                    write!(
                        f,
                        "{name}",
                        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)
        })
    }
}
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() {
                    write!(f, "!")?;
                }
                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)?;
                        self.print_type(inner_type, f, use_absolute, cx)?;
                        write!(f, ">")?;
                    } else {
                        write!(f, "{}<", print_anchor(ty.def_id(), last, cx))?;
                        self.print_type(inner_type, f, use_absolute, cx)?;
                        write!(f, ">")?;
                    }
                } else {
                    ty.print(cx).fmt(f)?;
                }
                write!(f, " 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,
        f: &mut fmt::Formatter<'_>,
        use_absolute: bool,
        cx: &Context<'_>,
    ) -> Result<(), fmt::Error> {
        if let clean::Type::Tuple(types) = type_
            && let [clean::Type::Generic(name)] = &types[..]
            && (self.kind.is_fake_variadic() || self.kind.is_auto())
        {
            // Hardcoded anchor library/core/src/primitive_docs.rs
            // Link should match `# Trait implementations`
            primitive_link_fragment(
                f,
                PrimitiveType::Tuple,
                format_args!("({name}₁, {name}₂, …, {name}ₙ)"),
                "#trait-implementations-1",
                cx,
            )?;
        } else if let clean::Type::Array(ty, len) = type_
            && let clean::Type::Generic(name) = &**ty
            && &len[..] == "1"
            && (self.kind.is_fake_variadic() || self.kind.is_auto())
        {
            primitive_link(f, PrimitiveType::Array, format_args!("[{name}; N]"), cx)?;
        } else if let clean::BareFunction(bare_fn) = &type_
            && let [clean::Parameter { type_: clean::Type::Generic(name), .. }] =
                &bare_fn.decl.inputs[..]
            && (self.kind.is_fake_variadic() || self.kind.is_auto())
        {
            // Hardcoded anchor library/core/src/primitive_docs.rs
            // Link should match `# Trait implementations`
            print_higher_ranked_params_with_space(&bare_fn.generic_params, cx, "for").fmt(f)?;
            bare_fn.safety.print_with_space().fmt(f)?;
            print_abi_with_space(bare_fn.abi).fmt(f)?;
            let ellipsis = if bare_fn.decl.c_variadic { ", ..." } else { "" };
            primitive_link_fragment(
                f,
                PrimitiveType::Tuple,
                format_args!("fn({name}₁, {name}₂, …, {name}ₙ{ellipsis})"),
                "#trait-implementations-1",
                cx,
            )?;
            // Write output.
            if !bare_fn.decl.output.is_unit() {
                write!(f, " -> ")?;
                fmt_type(&bare_fn.decl.output, f, use_absolute, cx)?;
            }
        } else if let clean::Type::Path { path } = type_
            && let Some(generics) = path.generics()
            && let Ok(ty) = generics.exactly_one()
            && self.kind.is_fake_variadic()
        {
            let wrapper = print_anchor(path.def_id(), path.last(), cx);
            if f.alternate() {
                write!(f, "{wrapper:#}<")?;
            } else {
                write!(f, "{wrapper}<")?;
            }
            self.print_type(ty, f, use_absolute, cx)?;
            if f.alternate() {
                write!(f, ">")?;
            } else {
                write!(f, ">")?;
            }
        } else {
            fmt_type(type_, f, use_absolute, cx)?;
        }
        Ok(())
    }
}
pub(crate) fn print_params(params: &[clean::Parameter], cx: &Context<'_>) -> impl Display {
    fmt::from_fn(move |f| {
        params
            .iter()
            .map(|param| {
                fmt::from_fn(|f| {
                    if let Some(name) = param.name {
                        write!(f, "{}: ", name)?;
                    }
                    param.type_.print(cx).fmt(f)
                })
            })
            .joined(", ", f)
    })
}
// Implements Write but only counts the bytes "written".
struct WriteCounter(usize);
impl std::fmt::Write for WriteCounter {
    fn write_str(&mut self, s: &str) -> fmt::Result {
        self.0 += s.len();
        Ok(())
    }
}
// Implements Display by emitting the given number of spaces.
struct Indent(usize);
impl Display for Indent {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        (0..self.0).for_each(|_| {
            f.write_char(' ').unwrap();
        });
        Ok(())
    }
}
impl clean::FnDecl {
    pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
        fmt::from_fn(move |f| {
            let ellipsis = if self.c_variadic { ", ..." } else { "" };
            if f.alternate() {
                write!(
                    f,
                    "({params:#}{ellipsis}){arrow:#}",
                    params = print_params(&self.inputs, cx),
                    ellipsis = ellipsis,
                    arrow = self.print_output(cx)
                )
            } else {
                write!(
                    f,
                    "({params}{ellipsis}){arrow}",
                    params = print_params(&self.inputs, cx),
                    ellipsis = ellipsis,
                    arrow = self.print_output(cx)
                )
            }
        })
    }
    /// * `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 ``/`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) }))
                .unwrap();
            // 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),
        // the declaration will be line-wrapped, with an indent of n spaces.
        line_wrapping_indent: Option,
        f: &mut fmt::Formatter<'_>,
        cx: &Context<'_>,
    ) -> fmt::Result {
        let amp = if f.alternate() { "&" } else { "&" };
        write!(f, "(")?;
        if let Some(n) = line_wrapping_indent
            && !self.inputs.is_empty()
        {
            write!(f, "\n{}", Indent(n + 4))?;
        }
        let last_input_index = self.inputs.len().checked_sub(1);
        for (i, param) in self.inputs.iter().enumerate() {
            if let Some(selfty) = param.to_receiver() {
                match selfty {
                    clean::SelfTy => {
                        write!(f, "self")?;
                    }
                    clean::BorrowedRef { lifetime, mutability, type_: box clean::SelfTy } => {
                        write!(f, "{amp}")?;
                        if let Some(lt) = lifetime {
                            write!(f, "{lt} ", lt = lt.print())?;
                        }
                        write!(f, "{mutability}self", mutability = mutability.print_with_space())?;
                    }
                    _ => {
                        write!(f, "self: ")?;
                        selfty.print(cx).fmt(f)?;
                    }
                }
            } else {
                if param.is_const {
                    write!(f, "const ")?;
                }
                if let Some(name) = param.name {
                    write!(f, "{}: ", name)?;
                }
                param.type_.print(cx).fmt(f)?;
            }
            match (line_wrapping_indent, last_input_index) {
                (_, None) => (),
                (None, Some(last_i)) if i != last_i => write!(f, ", ")?,
                (None, Some(_)) => (),
                (Some(n), Some(last_i)) if i != last_i => write!(f, ",\n{}", Indent(n + 4))?,
                (Some(_), Some(_)) => writeln!(f, ",")?,
            }
        }
        if self.c_variadic {
            match line_wrapping_indent {
                None => write!(f, ", ...")?,
                Some(n) => writeln!(f, "{}...", Indent(n + 4))?,
            };
        }
        match line_wrapping_indent {
            None => write!(f, ")")?,
            Some(n) => write!(f, "{})", Indent(n))?,
        };
        self.print_output(cx).fmt(f)
    }
    fn print_output(&self, cx: &Context<'_>) -> impl Display {
        fmt::from_fn(move |f| match &self.output {
            clean::Tuple(tys) if tys.is_empty() => Ok(()),
            ty if f.alternate() => {
                write!(f, " -> {:#}", ty.print(cx))
            }
            ty => write!(f, " -> {}", ty.print(cx)),
        })
    }
}
pub(crate) fn visibility_print_with_space(item: &clean::Item, cx: &Context<'_>) -> impl Display {
    fmt::from_fn(move |f| {
        if item.is_doc_hidden() {
            f.write_str("#[doc(hidden)] ")?;
        }
        match item.visibility(cx.tcx()) {
            None => {}
            Some(ty::Visibility::Public) => f.write_str("pub ")?,
            Some(ty::Visibility::Restricted(vis_did)) => {
                // FIXME(camelid): This may not work correctly if `item_did` is a module.
                //                 However, rustdoc currently never displays a module's
                //                 visibility, so it shouldn't matter.
                let parent_module =
                    find_nearest_parent_module(cx.tcx(), item.item_id.expect_def_id());
                if vis_did.is_crate_root() {
                    f.write_str("pub(crate) ")?;
                } else if parent_module == Some(vis_did) {
                    // `pub(in foo)` where `foo` is the parent module
                    // is the same as no visibility modifier; do nothing
                } else if parent_module
                    .and_then(|parent| find_nearest_parent_module(cx.tcx(), parent))
                    == Some(vis_did)
                {
                    f.write_str("pub(super) ")?;
                } else {
                    let path = cx.tcx().def_path(vis_did);
                    debug!("path={path:?}");
                    // modified from `resolved_path()` to work with `DefPathData`
                    let last_name = path.data.last().unwrap().data.get_opt_name().unwrap();
                    let anchor = print_anchor(vis_did, last_name, cx);
                    f.write_str("pub(in ")?;
                    for seg in &path.data[..path.data.len() - 1] {
                        write!(f, "{}::", seg.data.get_opt_name().unwrap())?;
                    }
                    write!(f, "{anchor}) ")?;
                }
            }
        }
        Ok(())
    })
}
pub(crate) trait PrintWithSpace {
    fn print_with_space(&self) -> &str;
}
impl PrintWithSpace for hir::Safety {
    fn print_with_space(&self) -> &str {
        self.prefix_str()
    }
}
impl PrintWithSpace for hir::HeaderSafety {
    fn print_with_space(&self) -> &str {
        match self {
            hir::HeaderSafety::SafeTargetFeatures => "",
            hir::HeaderSafety::Normal(safety) => safety.print_with_space(),
        }
    }
}
impl PrintWithSpace for hir::IsAsync {
    fn print_with_space(&self) -> &str {
        match self {
            hir::IsAsync::Async(_) => "async ",
            hir::IsAsync::NotAsync => "",
        }
    }
}
impl PrintWithSpace for hir::Mutability {
    fn print_with_space(&self) -> &str {
        match self {
            hir::Mutability::Not => "",
            hir::Mutability::Mut => "mut ",
        }
    }
}
pub(crate) fn print_constness_with_space(
    c: &hir::Constness,
    overall_stab: Option,
    const_stab: Option,
) -> &'static str {
    match c {
        hir::Constness::Const => match (overall_stab, const_stab) {
            // const stable...
            (_, Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }))
            // ...or when feature(staged_api) is not set...
            | (_, None)
            // ...or when const unstable, but overall unstable too
            | (None, Some(ConstStability { level: StabilityLevel::Unstable { .. }, .. })) => {
                "const "
            }
            // const unstable (and overall stable)
            (Some(_), Some(ConstStability { level: StabilityLevel::Unstable { .. }, .. })) => "",
        },
        // not const
        hir::Constness::NotConst => "",
    }
}
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))
                }
            }
            clean::ImportKind::Glob => {
                if self.source.path.segments.is_empty() {
                    write!(f, "use *;")
                } else {
                    write!(f, "use {}::*;", self.source.print(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(())
            }
        })
    }
}
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)?;
                    }
                }
            }
            Ok(())
        })
    }
}
pub(crate) fn print_abi_with_space(abi: ExternAbi) -> impl Display {
    fmt::from_fn(move |f| {
        let quot = if f.alternate() { "\"" } else { """ };
        match abi {
            ExternAbi::Rust => Ok(()),
            abi => write!(f, "extern {0}{1}{0} ", quot, abi.name()),
        }
    })
}
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),
        })
    }
}
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),
        })
    }
}