rustdoc: avoid allocating strings primitive link printing

This is aimed at hitting the allocator less in a function that
gets called a lot.
This commit is contained in:
Michael Howell 2023-10-20 18:26:20 -07:00
parent 249624b504
commit 4851cc9380

View File

@ -847,7 +847,7 @@ fn resolved_path<'cx>(
fn primitive_link( fn primitive_link(
f: &mut fmt::Formatter<'_>, f: &mut fmt::Formatter<'_>,
prim: clean::PrimitiveType, prim: clean::PrimitiveType,
name: &str, name: fmt::Arguments<'_>,
cx: &Context<'_>, cx: &Context<'_>,
) -> fmt::Result { ) -> fmt::Result {
primitive_link_fragment(f, prim, name, "", cx) primitive_link_fragment(f, prim, name, "", cx)
@ -856,7 +856,7 @@ fn primitive_link(
fn primitive_link_fragment( fn primitive_link_fragment(
f: &mut fmt::Formatter<'_>, f: &mut fmt::Formatter<'_>,
prim: clean::PrimitiveType, prim: clean::PrimitiveType,
name: &str, name: fmt::Arguments<'_>,
fragment: &str, fragment: &str,
cx: &Context<'_>, cx: &Context<'_>,
) -> fmt::Result { ) -> fmt::Result {
@ -907,7 +907,7 @@ fn primitive_link_fragment(
None => {} None => {}
} }
} }
f.write_str(name)?; std::fmt::Display::fmt(&name, f)?;
if needs_termination { if needs_termination {
write!(f, "</a>")?; write!(f, "</a>")?;
} }
@ -977,9 +977,11 @@ fn fmt_type<'cx>(
} }
clean::Infer => write!(f, "_"), clean::Infer => write!(f, "_"),
clean::Primitive(clean::PrimitiveType::Never) => { clean::Primitive(clean::PrimitiveType::Never) => {
primitive_link(f, PrimitiveType::Never, "!", cx) primitive_link(f, PrimitiveType::Never, format_args!("!"), cx)
}
clean::Primitive(prim) => {
primitive_link(f, prim, format_args!("{}", prim.as_sym().as_str()), cx)
} }
clean::Primitive(prim) => primitive_link(f, prim, prim.as_sym().as_str(), cx),
clean::BareFunction(ref decl) => { clean::BareFunction(ref decl) => {
if f.alternate() { if f.alternate() {
write!( write!(
@ -998,16 +1000,16 @@ fn fmt_type<'cx>(
decl.unsafety.print_with_space(), decl.unsafety.print_with_space(),
print_abi_with_space(decl.abi) print_abi_with_space(decl.abi)
)?; )?;
primitive_link(f, PrimitiveType::Fn, "fn", cx)?; primitive_link(f, PrimitiveType::Fn, format_args!("fn"), cx)?;
write!(f, "{}", decl.decl.print(cx)) write!(f, "{}", decl.decl.print(cx))
} }
} }
clean::Tuple(ref typs) => { clean::Tuple(ref typs) => {
match &typs[..] { match &typs[..] {
&[] => primitive_link(f, PrimitiveType::Unit, "()", cx), &[] => primitive_link(f, PrimitiveType::Unit, format_args!("()"), cx),
[one] => { [one] => {
if let clean::Generic(name) = one { if let clean::Generic(name) = one {
primitive_link(f, PrimitiveType::Tuple, &format!("({name},)"), cx) primitive_link(f, PrimitiveType::Tuple, format_args!("({name},)"), cx)
} else { } else {
write!(f, "(")?; write!(f, "(")?;
// Carry `f.alternate()` into this display w/o branching manually. // Carry `f.alternate()` into this display w/o branching manually.
@ -1028,7 +1030,10 @@ fn fmt_type<'cx>(
primitive_link( primitive_link(
f, f,
PrimitiveType::Tuple, PrimitiveType::Tuple,
&format!("({})", generic_names.iter().map(|s| s.as_str()).join(", ")), format_args!(
"({})",
generic_names.iter().map(|s| s.as_str()).join(", ")
),
cx, cx,
) )
} else { } else {
@ -1047,7 +1052,7 @@ fn fmt_type<'cx>(
} }
clean::Slice(ref t) => match **t { clean::Slice(ref t) => match **t {
clean::Generic(name) => { clean::Generic(name) => {
primitive_link(f, PrimitiveType::Slice, &format!("[{name}]"), cx) primitive_link(f, PrimitiveType::Slice, format_args!("[{name}]"), cx)
} }
_ => { _ => {
write!(f, "[")?; write!(f, "[")?;
@ -1059,7 +1064,7 @@ fn fmt_type<'cx>(
clean::Generic(name) if !f.alternate() => primitive_link( clean::Generic(name) if !f.alternate() => primitive_link(
f, f,
PrimitiveType::Array, PrimitiveType::Array,
&format!("[{name}; {n}]", n = Escape(n)), format_args!("[{name}; {n}]", n = Escape(n)),
cx, cx,
), ),
_ => { _ => {
@ -1069,7 +1074,12 @@ fn fmt_type<'cx>(
write!(f, "; {n}")?; write!(f, "; {n}")?;
} else { } else {
write!(f, "; ")?; write!(f, "; ")?;
primitive_link(f, PrimitiveType::Array, &format!("{n}", n = Escape(n)), cx)?; primitive_link(
f,
PrimitiveType::Array,
format_args!("{n}", n = Escape(n)),
cx,
)?;
} }
write!(f, "]") write!(f, "]")
} }
@ -1081,22 +1091,32 @@ fn fmt_type<'cx>(
}; };
if matches!(**t, clean::Generic(_)) || t.is_assoc_ty() { if matches!(**t, clean::Generic(_)) || t.is_assoc_ty() {
let text = if f.alternate() { let ty = t.print(cx);
format!("*{m} {ty:#}", ty = t.print(cx)) if f.alternate() {
primitive_link(
f,
clean::PrimitiveType::RawPointer,
format_args!("*{m} {ty:#}"),
cx,
)
} else { } else {
format!("*{m} {ty}", ty = t.print(cx)) primitive_link(
}; f,
primitive_link(f, clean::PrimitiveType::RawPointer, &text, cx) clean::PrimitiveType::RawPointer,
format_args!("*{m} {ty}"),
cx,
)
}
} else { } else {
primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{m} "), cx)?; primitive_link(f, clean::PrimitiveType::RawPointer, format_args!("*{m} "), cx)?;
fmt::Display::fmt(&t.print(cx), f) fmt::Display::fmt(&t.print(cx), f)
} }
} }
clean::BorrowedRef { lifetime: ref l, mutability, type_: ref ty } => { clean::BorrowedRef { lifetime: ref l, mutability, type_: ref ty } => {
let lt = match l { let lt = display_fn(|f| match l {
Some(l) => format!("{} ", l.print()), Some(l) => write!(f, "{} ", l.print()),
_ => String::new(), _ => Ok(()),
}; });
let m = mutability.print_with_space(); let m = mutability.print_with_space();
let amp = if f.alternate() { "&" } else { "&amp;" }; let amp = if f.alternate() { "&" } else { "&amp;" };
@ -1104,7 +1124,7 @@ fn fmt_type<'cx>(
return primitive_link( return primitive_link(
f, f,
PrimitiveType::Reference, PrimitiveType::Reference,
&format!("{amp}{lt}{m}{name}"), format_args!("{amp}{lt}{m}{name}"),
cx, cx,
); );
} }
@ -1254,7 +1274,7 @@ pub(crate) fn print<'a, 'tcx: 'a>(
{ {
// Hardcoded anchor library/core/src/primitive_docs.rs // Hardcoded anchor library/core/src/primitive_docs.rs
// Link should match `# Trait implementations` // Link should match `# Trait implementations`
primitive_link_fragment(f, PrimitiveType::Tuple, &format!("({name}₁, {name}₂, …, {name}ₙ)"), "#trait-implementations-1", cx)?; primitive_link_fragment(f, PrimitiveType::Tuple, format_args!("({name}₁, {name}₂, …, {name}ₙ)"), "#trait-implementations-1", cx)?;
} else if let clean::BareFunction(bare_fn) = &self.for_ && } else if let clean::BareFunction(bare_fn) = &self.for_ &&
let [clean::Argument { type_: clean::Type::Generic(name), .. }] = &bare_fn.decl.inputs.values[..] && let [clean::Argument { type_: clean::Type::Generic(name), .. }] = &bare_fn.decl.inputs.values[..] &&
(self.kind.is_fake_variadic() || self.kind.is_auto()) (self.kind.is_fake_variadic() || self.kind.is_auto())
@ -1281,7 +1301,7 @@ pub(crate) fn print<'a, 'tcx: 'a>(
} else { } else {
"" ""
}; };
primitive_link_fragment(f, PrimitiveType::Tuple, &format!("fn ({name}₁, {name}₂, …, {name}{ellipsis})"), "#trait-implementations-1", cx)?; primitive_link_fragment(f, PrimitiveType::Tuple, format_args!("fn ({name}₁, {name}₂, …, {name}{ellipsis})"), "#trait-implementations-1", cx)?;
// Write output. // Write output.
if !bare_fn.decl.output.is_unit() { if !bare_fn.decl.output.is_unit() {
write!(f, " -> ")?; write!(f, " -> ")?;
@ -1665,7 +1685,12 @@ pub(crate) fn print<'a, 'tcx: 'a>(
} }
let name = self.path.last(); let name = self.path.last();
if let hir::def::Res::PrimTy(p) = self.path.res { if let hir::def::Res::PrimTy(p) = self.path.res {
primitive_link(f, PrimitiveType::from(p), name.as_str(), cx)?; primitive_link(
f,
PrimitiveType::from(p),
format_args!("{}", name.as_str()),
cx,
)?;
} else { } else {
f.write_str(name.as_str())?; f.write_str(name.as_str())?;
} }