Skip to content

Commit e6152cd

Browse files
committed
Auto merge of #141573 - nnethercote:rustdoc-alloc-cleanups, r=camelid
rustdoc: cleanups relating to allocations These commits generally clean up the code a bit and also reduce allocation rates a bit. r? `@camelid`
2 parents 6de3a73 + 68f3216 commit e6152cd

File tree

10 files changed

+140
-146
lines changed

10 files changed

+140
-146
lines changed

src/librustdoc/clean/types.rs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ impl From<DefId> for ItemId {
107107
}
108108

109109
/// The crate currently being documented.
110-
#[derive(Clone, Debug)]
110+
#[derive(Debug)]
111111
pub(crate) struct Crate {
112112
pub(crate) module: Item,
113113
/// Only here so that they can be filtered through the rustdoc passes.
@@ -1655,9 +1655,7 @@ impl Type {
16551655
a.def_id() == b.def_id()
16561656
&& a.generics()
16571657
.zip(b.generics())
1658-
.map(|(ag, bg)| {
1659-
ag.iter().zip(bg.iter()).all(|(at, bt)| at.is_doc_subtype_of(bt, cache))
1660-
})
1658+
.map(|(ag, bg)| ag.zip(bg).all(|(at, bt)| at.is_doc_subtype_of(bt, cache)))
16611659
.unwrap_or(true)
16621660
}
16631661
// Other cases, such as primitives, just use recursion.
@@ -1730,7 +1728,7 @@ impl Type {
17301728
}
17311729
}
17321730

1733-
pub(crate) fn generics(&self) -> Option<Vec<&Type>> {
1731+
pub(crate) fn generics<'a>(&'a self) -> Option<impl Iterator<Item = &'a Type>> {
17341732
match self {
17351733
Type::Path { path, .. } => path.generics(),
17361734
_ => None,
@@ -2288,17 +2286,13 @@ impl Path {
22882286
self.segments.last().map(|seg| &seg.args)
22892287
}
22902288

2291-
pub(crate) fn generics(&self) -> Option<Vec<&Type>> {
2289+
pub(crate) fn generics<'a>(&'a self) -> Option<impl Iterator<Item = &'a Type>> {
22922290
self.segments.last().and_then(|seg| {
22932291
if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
2294-
Some(
2295-
args.iter()
2296-
.filter_map(|arg| match arg {
2297-
GenericArg::Type(ty) => Some(ty),
2298-
_ => None,
2299-
})
2300-
.collect(),
2301-
)
2292+
Some(args.iter().filter_map(|arg| match arg {
2293+
GenericArg::Type(ty) => Some(ty),
2294+
_ => None,
2295+
}))
23022296
} else {
23032297
None
23042298
}

src/librustdoc/html/format.rs

Lines changed: 67 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,12 @@
77
//! some of them support an alternate format that emits text, but that should
88
//! not be used external to this module.
99
10-
use std::borrow::Cow;
1110
use std::cmp::Ordering;
1211
use std::fmt::{self, Display, Write};
1312
use std::iter::{self, once};
1413
use std::slice;
1514

16-
use itertools::Either;
15+
use itertools::{Either, Itertools};
1716
use rustc_abi::ExternAbi;
1817
use rustc_attr_data_structures::{ConstStability, StabilityLevel, StableSince};
1918
use rustc_data_structures::fx::FxHashSet;
@@ -483,12 +482,12 @@ fn generate_item_def_id_path(
483482
let mut is_remote = false;
484483

485484
let url_parts = url_parts(cx.cache(), def_id, module_fqp, &cx.current, &mut is_remote)?;
486-
let (url_parts, shortty, fqp) = make_href(root_path, shortty, url_parts, &fqp, is_remote)?;
487-
if def_id == original_def_id {
488-
return Ok((url_parts, shortty, fqp));
489-
}
490-
let kind = ItemType::from_def_kind(original_def_kind, Some(def_kind));
491-
Ok((format!("{url_parts}#{kind}.{}", tcx.item_name(original_def_id)), shortty, fqp))
485+
let mut url_parts = make_href(root_path, shortty, url_parts, &fqp, is_remote);
486+
if def_id != original_def_id {
487+
let kind = ItemType::from_def_kind(original_def_kind, Some(def_kind));
488+
url_parts = format!("{url_parts}#{kind}.{}", tcx.item_name(original_def_id))
489+
};
490+
Ok((url_parts, shortty, fqp))
492491
}
493492

494493
fn to_module_fqp(shortty: ItemType, fqp: &[Symbol]) -> &[Symbol] {
@@ -510,7 +509,7 @@ fn url_parts(
510509
builder.extend(module_fqp.iter().copied());
511510
Ok(builder)
512511
}
513-
ExternalLocation::Local => Ok(href_relative_parts(module_fqp, relative_to).collect()),
512+
ExternalLocation::Local => Ok(href_relative_parts(module_fqp, relative_to)),
514513
ExternalLocation::Unknown => Err(HrefError::DocumentationNotBuilt),
515514
}
516515
}
@@ -521,7 +520,7 @@ fn make_href(
521520
mut url_parts: UrlPartsBuilder,
522521
fqp: &[Symbol],
523522
is_remote: bool,
524-
) -> Result<(String, ItemType, Vec<Symbol>), HrefError> {
523+
) -> String {
525524
if !is_remote && let Some(root_path) = root_path {
526525
let root = root_path.trim_end_matches('/');
527526
url_parts.push_front(root);
@@ -536,7 +535,7 @@ fn make_href(
536535
url_parts.push_fmt(format_args!("{shortty}.{last}.html"));
537536
}
538537
}
539-
Ok((url_parts.finish(), shortty, fqp.to_vec()))
538+
url_parts.finish()
540539
}
541540

542541
pub(crate) fn href_with_root_path(
@@ -587,7 +586,7 @@ pub(crate) fn href_with_root_path(
587586
Some(&(ref fqp, shortty)) => (fqp, shortty, {
588587
let module_fqp = to_module_fqp(shortty, fqp.as_slice());
589588
debug!(?fqp, ?shortty, ?module_fqp);
590-
href_relative_parts(module_fqp, relative_to).collect()
589+
href_relative_parts(module_fqp, relative_to)
591590
}),
592591
None => {
593592
// Associated items are handled differently with "jump to def". The anchor is generated
@@ -606,7 +605,8 @@ pub(crate) fn href_with_root_path(
606605
}
607606
}
608607
};
609-
make_href(root_path, shortty, url_parts, fqp, is_remote)
608+
let url_parts = make_href(root_path, shortty, url_parts, &fqp, is_remote);
609+
Ok((url_parts, shortty, fqp.clone()))
610610
}
611611

612612
pub(crate) fn href(
@@ -619,34 +619,30 @@ pub(crate) fn href(
619619
/// Both paths should only be modules.
620620
/// This is because modules get their own directories; that is, `std::vec` and `std::vec::Vec` will
621621
/// both need `../iter/trait.Iterator.html` to get at the iterator trait.
622-
pub(crate) fn href_relative_parts<'fqp>(
623-
fqp: &'fqp [Symbol],
624-
relative_to_fqp: &[Symbol],
625-
) -> Box<dyn Iterator<Item = Symbol> + 'fqp> {
622+
pub(crate) fn href_relative_parts(fqp: &[Symbol], relative_to_fqp: &[Symbol]) -> UrlPartsBuilder {
626623
for (i, (f, r)) in fqp.iter().zip(relative_to_fqp.iter()).enumerate() {
627624
// e.g. linking to std::iter from std::vec (`dissimilar_part_count` will be 1)
628625
if f != r {
629626
let dissimilar_part_count = relative_to_fqp.len() - i;
630627
let fqp_module = &fqp[i..];
631-
return Box::new(
632-
iter::repeat_n(sym::dotdot, dissimilar_part_count)
633-
.chain(fqp_module.iter().copied()),
634-
);
628+
return iter::repeat_n(sym::dotdot, dissimilar_part_count)
629+
.chain(fqp_module.iter().copied())
630+
.collect();
635631
}
636632
}
637633
match relative_to_fqp.len().cmp(&fqp.len()) {
638634
Ordering::Less => {
639635
// e.g. linking to std::sync::atomic from std::sync
640-
Box::new(fqp[relative_to_fqp.len()..fqp.len()].iter().copied())
636+
fqp[relative_to_fqp.len()..fqp.len()].iter().copied().collect()
641637
}
642638
Ordering::Greater => {
643639
// e.g. linking to std::sync from std::sync::atomic
644640
let dissimilar_part_count = relative_to_fqp.len() - fqp.len();
645-
Box::new(iter::repeat_n(sym::dotdot, dissimilar_part_count))
641+
iter::repeat_n(sym::dotdot, dissimilar_part_count).collect()
646642
}
647643
Ordering::Equal => {
648644
// linking to the same module
649-
Box::new(iter::empty())
645+
UrlPartsBuilder::new()
650646
}
651647
}
652648
}
@@ -708,13 +704,13 @@ fn resolved_path(
708704
f,
709705
"{path}::{anchor}",
710706
path = join_with_double_colon(&fqp[..fqp.len() - 1]),
711-
anchor = anchor(did, *fqp.last().unwrap(), cx)
707+
anchor = print_anchor(did, *fqp.last().unwrap(), cx)
712708
)
713709
} else {
714710
write!(f, "{}", last.name)
715711
}
716712
} else {
717-
write!(f, "{}", anchor(did, last.name, cx))
713+
write!(f, "{}", print_anchor(did, last.name, cx))
718714
}
719715
});
720716
write!(w, "{path}{args}", args = last.args.print(cx))?;
@@ -800,7 +796,7 @@ fn primitive_link_fragment(
800796
Ok(())
801797
}
802798

803-
fn tybounds(
799+
fn print_tybounds(
804800
bounds: &[clean::PolyTrait],
805801
lt: &Option<clean::Lifetime>,
806802
cx: &Context<'_>,
@@ -832,7 +828,7 @@ fn print_higher_ranked_params_with_space(
832828
})
833829
}
834830

835-
pub(crate) fn anchor(did: DefId, text: Symbol, cx: &Context<'_>) -> impl Display {
831+
pub(crate) fn print_anchor(did: DefId, text: Symbol, cx: &Context<'_>) -> impl Display {
836832
fmt::from_fn(move |f| {
837833
let parts = href(did, cx);
838834
if let Ok((url, short_ty, fqp)) = parts {
@@ -866,7 +862,7 @@ fn fmt_type(
866862
}
867863
clean::DynTrait(bounds, lt) => {
868864
f.write_str("dyn ")?;
869-
tybounds(bounds, lt, cx).fmt(f)
865+
print_tybounds(bounds, lt, cx).fmt(f)
870866
}
871867
clean::Infer => write!(f, "_"),
872868
clean::Primitive(clean::PrimitiveType::Never) => {
@@ -1122,16 +1118,16 @@ impl clean::Impl {
11221118
write!(f, "!")?;
11231119
}
11241120
if self.kind.is_fake_variadic()
1125-
&& let generics = ty.generics()
1126-
&& let &[inner_type] = generics.as_ref().map_or(&[][..], |v| &v[..])
1121+
&& let Some(generics) = ty.generics()
1122+
&& let Ok(inner_type) = generics.exactly_one()
11271123
{
11281124
let last = ty.last();
11291125
if f.alternate() {
11301126
write!(f, "{}<", last)?;
11311127
self.print_type(inner_type, f, use_absolute, cx)?;
11321128
write!(f, ">")?;
11331129
} else {
1134-
write!(f, "{}&lt;", anchor(ty.def_id(), last, cx))?;
1130+
write!(f, "{}&lt;", print_anchor(ty.def_id(), last, cx))?;
11351131
self.print_type(inner_type, f, use_absolute, cx)?;
11361132
write!(f, "&gt;")?;
11371133
}
@@ -1202,11 +1198,10 @@ impl clean::Impl {
12021198
}
12031199
} else if let clean::Type::Path { path } = type_
12041200
&& let Some(generics) = path.generics()
1205-
&& generics.len() == 1
1201+
&& let Ok(ty) = generics.exactly_one()
12061202
&& self.kind.is_fake_variadic()
12071203
{
1208-
let ty = generics[0];
1209-
let wrapper = anchor(path.def_id(), path.last(), cx);
1204+
let wrapper = print_anchor(path.def_id(), path.last(), cx);
12101205
if f.alternate() {
12111206
write!(f, "{wrapper:#}&lt;")?;
12121207
} else {
@@ -1394,50 +1389,47 @@ impl clean::FnDecl {
13941389
}
13951390

13961391
pub(crate) fn visibility_print_with_space(item: &clean::Item, cx: &Context<'_>) -> impl Display {
1397-
use std::fmt::Write as _;
1398-
let vis: Cow<'static, str> = match item.visibility(cx.tcx()) {
1399-
None => "".into(),
1400-
Some(ty::Visibility::Public) => "pub ".into(),
1401-
Some(ty::Visibility::Restricted(vis_did)) => {
1402-
// FIXME(camelid): This may not work correctly if `item_did` is a module.
1403-
// However, rustdoc currently never displays a module's
1404-
// visibility, so it shouldn't matter.
1405-
let parent_module = find_nearest_parent_module(cx.tcx(), item.item_id.expect_def_id());
1406-
1407-
if vis_did.is_crate_root() {
1408-
"pub(crate) ".into()
1409-
} else if parent_module == Some(vis_did) {
1410-
// `pub(in foo)` where `foo` is the parent module
1411-
// is the same as no visibility modifier
1412-
"".into()
1413-
} else if parent_module.and_then(|parent| find_nearest_parent_module(cx.tcx(), parent))
1414-
== Some(vis_did)
1415-
{
1416-
"pub(super) ".into()
1417-
} else {
1418-
let path = cx.tcx().def_path(vis_did);
1419-
debug!("path={path:?}");
1420-
// modified from `resolved_path()` to work with `DefPathData`
1421-
let last_name = path.data.last().unwrap().data.get_opt_name().unwrap();
1422-
let anchor = anchor(vis_did, last_name, cx);
1423-
1424-
let mut s = "pub(in ".to_owned();
1425-
for seg in &path.data[..path.data.len() - 1] {
1426-
let _ = write!(s, "{}::", seg.data.get_opt_name().unwrap());
1427-
}
1428-
let _ = write!(s, "{anchor}) ");
1429-
s.into()
1430-
}
1431-
}
1432-
};
1433-
1434-
let is_doc_hidden = item.is_doc_hidden();
14351392
fmt::from_fn(move |f| {
1436-
if is_doc_hidden {
1393+
if item.is_doc_hidden() {
14371394
f.write_str("#[doc(hidden)] ")?;
14381395
}
14391396

1440-
f.write_str(&vis)
1397+
match item.visibility(cx.tcx()) {
1398+
None => {}
1399+
Some(ty::Visibility::Public) => f.write_str("pub ")?,
1400+
Some(ty::Visibility::Restricted(vis_did)) => {
1401+
// FIXME(camelid): This may not work correctly if `item_did` is a module.
1402+
// However, rustdoc currently never displays a module's
1403+
// visibility, so it shouldn't matter.
1404+
let parent_module =
1405+
find_nearest_parent_module(cx.tcx(), item.item_id.expect_def_id());
1406+
1407+
if vis_did.is_crate_root() {
1408+
f.write_str("pub(crate) ")?;
1409+
} else if parent_module == Some(vis_did) {
1410+
// `pub(in foo)` where `foo` is the parent module
1411+
// is the same as no visibility modifier; do nothing
1412+
} else if parent_module
1413+
.and_then(|parent| find_nearest_parent_module(cx.tcx(), parent))
1414+
== Some(vis_did)
1415+
{
1416+
f.write_str("pub(super) ")?;
1417+
} else {
1418+
let path = cx.tcx().def_path(vis_did);
1419+
debug!("path={path:?}");
1420+
// modified from `resolved_path()` to work with `DefPathData`
1421+
let last_name = path.data.last().unwrap().data.get_opt_name().unwrap();
1422+
let anchor = print_anchor(vis_did, last_name, cx);
1423+
1424+
f.write_str("pub(in ")?;
1425+
for seg in &path.data[..path.data.len() - 1] {
1426+
write!(f, "{}::", seg.data.get_opt_name().unwrap())?;
1427+
}
1428+
write!(f, "{anchor}) ")?;
1429+
}
1430+
}
1431+
}
1432+
Ok(())
14411433
})
14421434
}
14431435

src/librustdoc/html/layout.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use super::static_files::{STATIC_FILES, StaticFiles};
88
use crate::externalfiles::ExternalHtml;
99
use crate::html::render::{StylePath, ensure_trailing_slash};
1010

11-
#[derive(Clone)]
1211
pub(crate) struct Layout {
1312
pub(crate) logo: String,
1413
pub(crate) favicon: String,

src/librustdoc/html/markdown.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ fn slugify(c: char) -> Option<char> {
195195
}
196196
}
197197

198-
#[derive(Clone, Debug)]
198+
#[derive(Debug)]
199199
pub struct Playground {
200200
pub crate_name: Option<Symbol>,
201201
pub url: String,

src/librustdoc/html/render/context.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_span::edition::Edition;
1414
use rustc_span::{FileName, Symbol, sym};
1515
use tracing::info;
1616

17-
use super::print_item::{full_path, item_path, print_item};
17+
use super::print_item::{full_path, print_item, print_item_path};
1818
use super::sidebar::{ModuleLike, Sidebar, print_sidebar, sidebar_module_like};
1919
use super::{AllTypes, LinkFromSrc, StylePath, collect_spans_and_sources, scrape_examples_help};
2020
use crate::clean::types::ExternalLocation;
@@ -266,7 +266,7 @@ impl<'tcx> Context<'tcx> {
266266
for name in &names[..names.len() - 1] {
267267
write!(f, "{name}/")?;
268268
}
269-
write!(f, "{}", item_path(ty, names.last().unwrap().as_str()))
269+
write!(f, "{}", print_item_path(ty, names.last().unwrap().as_str()))
270270
});
271271
match self.shared.redirections {
272272
Some(ref redirections) => {
@@ -278,7 +278,7 @@ impl<'tcx> Context<'tcx> {
278278
let _ = write!(
279279
current_path,
280280
"{}",
281-
item_path(ty, names.last().unwrap().as_str())
281+
print_item_path(ty, names.last().unwrap().as_str())
282282
);
283283
redirections.borrow_mut().insert(current_path, path.to_string());
284284
}
@@ -847,7 +847,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
847847
if !buf.is_empty() {
848848
let name = item.name.as_ref().unwrap();
849849
let item_type = item.type_();
850-
let file_name = item_path(item_type, name.as_str()).to_string();
850+
let file_name = print_item_path(item_type, name.as_str()).to_string();
851851
self.shared.ensure_dir(&self.dst)?;
852852
let joint_dst = self.dst.join(&file_name);
853853
self.shared.fs.write(joint_dst, buf)?;

0 commit comments

Comments
 (0)