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`
This commit is contained in:
commit
e6152cdf5b
10 changed files with 140 additions and 146 deletions
|
|
@ -107,7 +107,7 @@ impl From<DefId> for ItemId {
|
|||
}
|
||||
|
||||
/// The crate currently being documented.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Crate {
|
||||
pub(crate) module: Item,
|
||||
/// Only here so that they can be filtered through the rustdoc passes.
|
||||
|
|
@ -1655,9 +1655,7 @@ impl Type {
|
|||
a.def_id() == b.def_id()
|
||||
&& a.generics()
|
||||
.zip(b.generics())
|
||||
.map(|(ag, bg)| {
|
||||
ag.iter().zip(bg.iter()).all(|(at, bt)| at.is_doc_subtype_of(bt, cache))
|
||||
})
|
||||
.map(|(ag, bg)| ag.zip(bg).all(|(at, bt)| at.is_doc_subtype_of(bt, cache)))
|
||||
.unwrap_or(true)
|
||||
}
|
||||
// Other cases, such as primitives, just use recursion.
|
||||
|
|
@ -1730,7 +1728,7 @@ impl Type {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn generics(&self) -> Option<Vec<&Type>> {
|
||||
pub(crate) fn generics<'a>(&'a self) -> Option<impl Iterator<Item = &'a Type>> {
|
||||
match self {
|
||||
Type::Path { path, .. } => path.generics(),
|
||||
_ => None,
|
||||
|
|
@ -2288,17 +2286,13 @@ impl Path {
|
|||
self.segments.last().map(|seg| &seg.args)
|
||||
}
|
||||
|
||||
pub(crate) fn generics(&self) -> Option<Vec<&Type>> {
|
||||
pub(crate) fn generics<'a>(&'a self) -> Option<impl Iterator<Item = &'a Type>> {
|
||||
self.segments.last().and_then(|seg| {
|
||||
if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
|
||||
Some(
|
||||
args.iter()
|
||||
.filter_map(|arg| match arg {
|
||||
GenericArg::Type(ty) => Some(ty),
|
||||
_ => None,
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
Some(args.iter().filter_map(|arg| match arg {
|
||||
GenericArg::Type(ty) => Some(ty),
|
||||
_ => None,
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,13 +7,12 @@
|
|||
//! some of them support an alternate format that emits text, but that should
|
||||
//! not be used external to this module.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt::{self, Display, Write};
|
||||
use std::iter::{self, once};
|
||||
use std::slice;
|
||||
|
||||
use itertools::Either;
|
||||
use itertools::{Either, Itertools};
|
||||
use rustc_abi::ExternAbi;
|
||||
use rustc_attr_data_structures::{ConstStability, StabilityLevel, StableSince};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
|
|
@ -483,12 +482,12 @@ fn generate_item_def_id_path(
|
|||
let mut is_remote = false;
|
||||
|
||||
let url_parts = url_parts(cx.cache(), def_id, module_fqp, &cx.current, &mut is_remote)?;
|
||||
let (url_parts, shortty, fqp) = make_href(root_path, shortty, url_parts, &fqp, is_remote)?;
|
||||
if def_id == original_def_id {
|
||||
return Ok((url_parts, shortty, fqp));
|
||||
}
|
||||
let kind = ItemType::from_def_kind(original_def_kind, Some(def_kind));
|
||||
Ok((format!("{url_parts}#{kind}.{}", tcx.item_name(original_def_id)), shortty, fqp))
|
||||
let mut url_parts = make_href(root_path, shortty, url_parts, &fqp, is_remote);
|
||||
if def_id != original_def_id {
|
||||
let kind = ItemType::from_def_kind(original_def_kind, Some(def_kind));
|
||||
url_parts = format!("{url_parts}#{kind}.{}", tcx.item_name(original_def_id))
|
||||
};
|
||||
Ok((url_parts, shortty, fqp))
|
||||
}
|
||||
|
||||
fn to_module_fqp(shortty: ItemType, fqp: &[Symbol]) -> &[Symbol] {
|
||||
|
|
@ -510,7 +509,7 @@ fn url_parts(
|
|||
builder.extend(module_fqp.iter().copied());
|
||||
Ok(builder)
|
||||
}
|
||||
ExternalLocation::Local => Ok(href_relative_parts(module_fqp, relative_to).collect()),
|
||||
ExternalLocation::Local => Ok(href_relative_parts(module_fqp, relative_to)),
|
||||
ExternalLocation::Unknown => Err(HrefError::DocumentationNotBuilt),
|
||||
}
|
||||
}
|
||||
|
|
@ -521,7 +520,7 @@ fn make_href(
|
|||
mut url_parts: UrlPartsBuilder,
|
||||
fqp: &[Symbol],
|
||||
is_remote: bool,
|
||||
) -> Result<(String, ItemType, Vec<Symbol>), HrefError> {
|
||||
) -> String {
|
||||
if !is_remote && let Some(root_path) = root_path {
|
||||
let root = root_path.trim_end_matches('/');
|
||||
url_parts.push_front(root);
|
||||
|
|
@ -536,7 +535,7 @@ fn make_href(
|
|||
url_parts.push_fmt(format_args!("{shortty}.{last}.html"));
|
||||
}
|
||||
}
|
||||
Ok((url_parts.finish(), shortty, fqp.to_vec()))
|
||||
url_parts.finish()
|
||||
}
|
||||
|
||||
pub(crate) fn href_with_root_path(
|
||||
|
|
@ -587,7 +586,7 @@ pub(crate) fn href_with_root_path(
|
|||
Some(&(ref fqp, shortty)) => (fqp, shortty, {
|
||||
let module_fqp = to_module_fqp(shortty, fqp.as_slice());
|
||||
debug!(?fqp, ?shortty, ?module_fqp);
|
||||
href_relative_parts(module_fqp, relative_to).collect()
|
||||
href_relative_parts(module_fqp, relative_to)
|
||||
}),
|
||||
None => {
|
||||
// Associated items are handled differently with "jump to def". The anchor is generated
|
||||
|
|
@ -606,7 +605,8 @@ pub(crate) fn href_with_root_path(
|
|||
}
|
||||
}
|
||||
};
|
||||
make_href(root_path, shortty, url_parts, fqp, is_remote)
|
||||
let url_parts = make_href(root_path, shortty, url_parts, &fqp, is_remote);
|
||||
Ok((url_parts, shortty, fqp.clone()))
|
||||
}
|
||||
|
||||
pub(crate) fn href(
|
||||
|
|
@ -619,34 +619,30 @@ pub(crate) fn href(
|
|||
/// Both paths should only be modules.
|
||||
/// This is because modules get their own directories; that is, `std::vec` and `std::vec::Vec` will
|
||||
/// both need `../iter/trait.Iterator.html` to get at the iterator trait.
|
||||
pub(crate) fn href_relative_parts<'fqp>(
|
||||
fqp: &'fqp [Symbol],
|
||||
relative_to_fqp: &[Symbol],
|
||||
) -> Box<dyn Iterator<Item = Symbol> + 'fqp> {
|
||||
pub(crate) fn href_relative_parts(fqp: &[Symbol], relative_to_fqp: &[Symbol]) -> UrlPartsBuilder {
|
||||
for (i, (f, r)) in fqp.iter().zip(relative_to_fqp.iter()).enumerate() {
|
||||
// e.g. linking to std::iter from std::vec (`dissimilar_part_count` will be 1)
|
||||
if f != r {
|
||||
let dissimilar_part_count = relative_to_fqp.len() - i;
|
||||
let fqp_module = &fqp[i..];
|
||||
return Box::new(
|
||||
iter::repeat_n(sym::dotdot, dissimilar_part_count)
|
||||
.chain(fqp_module.iter().copied()),
|
||||
);
|
||||
return iter::repeat_n(sym::dotdot, dissimilar_part_count)
|
||||
.chain(fqp_module.iter().copied())
|
||||
.collect();
|
||||
}
|
||||
}
|
||||
match relative_to_fqp.len().cmp(&fqp.len()) {
|
||||
Ordering::Less => {
|
||||
// e.g. linking to std::sync::atomic from std::sync
|
||||
Box::new(fqp[relative_to_fqp.len()..fqp.len()].iter().copied())
|
||||
fqp[relative_to_fqp.len()..fqp.len()].iter().copied().collect()
|
||||
}
|
||||
Ordering::Greater => {
|
||||
// e.g. linking to std::sync from std::sync::atomic
|
||||
let dissimilar_part_count = relative_to_fqp.len() - fqp.len();
|
||||
Box::new(iter::repeat_n(sym::dotdot, dissimilar_part_count))
|
||||
iter::repeat_n(sym::dotdot, dissimilar_part_count).collect()
|
||||
}
|
||||
Ordering::Equal => {
|
||||
// linking to the same module
|
||||
Box::new(iter::empty())
|
||||
UrlPartsBuilder::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -708,13 +704,13 @@ fn resolved_path(
|
|||
f,
|
||||
"{path}::{anchor}",
|
||||
path = join_with_double_colon(&fqp[..fqp.len() - 1]),
|
||||
anchor = anchor(did, *fqp.last().unwrap(), cx)
|
||||
anchor = print_anchor(did, *fqp.last().unwrap(), cx)
|
||||
)
|
||||
} else {
|
||||
write!(f, "{}", last.name)
|
||||
}
|
||||
} else {
|
||||
write!(f, "{}", anchor(did, last.name, cx))
|
||||
write!(f, "{}", print_anchor(did, last.name, cx))
|
||||
}
|
||||
});
|
||||
write!(w, "{path}{args}", args = last.args.print(cx))?;
|
||||
|
|
@ -800,7 +796,7 @@ fn primitive_link_fragment(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn tybounds(
|
||||
fn print_tybounds(
|
||||
bounds: &[clean::PolyTrait],
|
||||
lt: &Option<clean::Lifetime>,
|
||||
cx: &Context<'_>,
|
||||
|
|
@ -832,7 +828,7 @@ fn print_higher_ranked_params_with_space(
|
|||
})
|
||||
}
|
||||
|
||||
pub(crate) fn anchor(did: DefId, text: Symbol, cx: &Context<'_>) -> impl Display {
|
||||
pub(crate) fn print_anchor(did: DefId, text: Symbol, cx: &Context<'_>) -> impl Display {
|
||||
fmt::from_fn(move |f| {
|
||||
let parts = href(did, cx);
|
||||
if let Ok((url, short_ty, fqp)) = parts {
|
||||
|
|
@ -866,7 +862,7 @@ fn fmt_type(
|
|||
}
|
||||
clean::DynTrait(bounds, lt) => {
|
||||
f.write_str("dyn ")?;
|
||||
tybounds(bounds, lt, cx).fmt(f)
|
||||
print_tybounds(bounds, lt, cx).fmt(f)
|
||||
}
|
||||
clean::Infer => write!(f, "_"),
|
||||
clean::Primitive(clean::PrimitiveType::Never) => {
|
||||
|
|
@ -1122,8 +1118,8 @@ impl clean::Impl {
|
|||
write!(f, "!")?;
|
||||
}
|
||||
if self.kind.is_fake_variadic()
|
||||
&& let generics = ty.generics()
|
||||
&& let &[inner_type] = generics.as_ref().map_or(&[][..], |v| &v[..])
|
||||
&& let Some(generics) = ty.generics()
|
||||
&& let Ok(inner_type) = generics.exactly_one()
|
||||
{
|
||||
let last = ty.last();
|
||||
if f.alternate() {
|
||||
|
|
@ -1131,7 +1127,7 @@ impl clean::Impl {
|
|||
self.print_type(inner_type, f, use_absolute, cx)?;
|
||||
write!(f, ">")?;
|
||||
} else {
|
||||
write!(f, "{}<", anchor(ty.def_id(), last, cx))?;
|
||||
write!(f, "{}<", print_anchor(ty.def_id(), last, cx))?;
|
||||
self.print_type(inner_type, f, use_absolute, cx)?;
|
||||
write!(f, ">")?;
|
||||
}
|
||||
|
|
@ -1202,11 +1198,10 @@ impl clean::Impl {
|
|||
}
|
||||
} else if let clean::Type::Path { path } = type_
|
||||
&& let Some(generics) = path.generics()
|
||||
&& generics.len() == 1
|
||||
&& let Ok(ty) = generics.exactly_one()
|
||||
&& self.kind.is_fake_variadic()
|
||||
{
|
||||
let ty = generics[0];
|
||||
let wrapper = anchor(path.def_id(), path.last(), cx);
|
||||
let wrapper = print_anchor(path.def_id(), path.last(), cx);
|
||||
if f.alternate() {
|
||||
write!(f, "{wrapper:#}<")?;
|
||||
} else {
|
||||
|
|
@ -1394,50 +1389,47 @@ impl clean::FnDecl {
|
|||
}
|
||||
|
||||
pub(crate) fn visibility_print_with_space(item: &clean::Item, cx: &Context<'_>) -> impl Display {
|
||||
use std::fmt::Write as _;
|
||||
let vis: Cow<'static, str> = match item.visibility(cx.tcx()) {
|
||||
None => "".into(),
|
||||
Some(ty::Visibility::Public) => "pub ".into(),
|
||||
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() {
|
||||
"pub(crate) ".into()
|
||||
} else if parent_module == Some(vis_did) {
|
||||
// `pub(in foo)` where `foo` is the parent module
|
||||
// is the same as no visibility modifier
|
||||
"".into()
|
||||
} else if parent_module.and_then(|parent| find_nearest_parent_module(cx.tcx(), parent))
|
||||
== Some(vis_did)
|
||||
{
|
||||
"pub(super) ".into()
|
||||
} 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 = anchor(vis_did, last_name, cx);
|
||||
|
||||
let mut s = "pub(in ".to_owned();
|
||||
for seg in &path.data[..path.data.len() - 1] {
|
||||
let _ = write!(s, "{}::", seg.data.get_opt_name().unwrap());
|
||||
}
|
||||
let _ = write!(s, "{anchor}) ");
|
||||
s.into()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let is_doc_hidden = item.is_doc_hidden();
|
||||
fmt::from_fn(move |f| {
|
||||
if is_doc_hidden {
|
||||
if item.is_doc_hidden() {
|
||||
f.write_str("#[doc(hidden)] ")?;
|
||||
}
|
||||
|
||||
f.write_str(&vis)
|
||||
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(())
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ use super::static_files::{STATIC_FILES, StaticFiles};
|
|||
use crate::externalfiles::ExternalHtml;
|
||||
use crate::html::render::{StylePath, ensure_trailing_slash};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct Layout {
|
||||
pub(crate) logo: String,
|
||||
pub(crate) favicon: String,
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ fn slugify(c: char) -> Option<char> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub struct Playground {
|
||||
pub crate_name: Option<Symbol>,
|
||||
pub url: String,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use rustc_span::edition::Edition;
|
|||
use rustc_span::{FileName, Symbol, sym};
|
||||
use tracing::info;
|
||||
|
||||
use super::print_item::{full_path, item_path, print_item};
|
||||
use super::print_item::{full_path, print_item, print_item_path};
|
||||
use super::sidebar::{ModuleLike, Sidebar, print_sidebar, sidebar_module_like};
|
||||
use super::{AllTypes, LinkFromSrc, StylePath, collect_spans_and_sources, scrape_examples_help};
|
||||
use crate::clean::types::ExternalLocation;
|
||||
|
|
@ -266,7 +266,7 @@ impl<'tcx> Context<'tcx> {
|
|||
for name in &names[..names.len() - 1] {
|
||||
write!(f, "{name}/")?;
|
||||
}
|
||||
write!(f, "{}", item_path(ty, names.last().unwrap().as_str()))
|
||||
write!(f, "{}", print_item_path(ty, names.last().unwrap().as_str()))
|
||||
});
|
||||
match self.shared.redirections {
|
||||
Some(ref redirections) => {
|
||||
|
|
@ -278,7 +278,7 @@ impl<'tcx> Context<'tcx> {
|
|||
let _ = write!(
|
||||
current_path,
|
||||
"{}",
|
||||
item_path(ty, names.last().unwrap().as_str())
|
||||
print_item_path(ty, names.last().unwrap().as_str())
|
||||
);
|
||||
redirections.borrow_mut().insert(current_path, path.to_string());
|
||||
}
|
||||
|
|
@ -847,7 +847,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
|
|||
if !buf.is_empty() {
|
||||
let name = item.name.as_ref().unwrap();
|
||||
let item_type = item.type_();
|
||||
let file_name = item_path(item_type, name.as_str()).to_string();
|
||||
let file_name = print_item_path(item_type, name.as_str()).to_string();
|
||||
self.shared.ensure_dir(&self.dst)?;
|
||||
let joint_dst = self.dst.join(&file_name);
|
||||
self.shared.fs.write(joint_dst, buf)?;
|
||||
|
|
|
|||
|
|
@ -2548,7 +2548,7 @@ fn item_ty_to_section(ty: ItemType) -> ItemSection {
|
|||
/// types are re-exported, we don't use the corresponding
|
||||
/// entry from the js file, as inlining will have already
|
||||
/// picked up the impl
|
||||
fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> {
|
||||
fn collect_paths_for_type(first_ty: &clean::Type, cache: &Cache) -> Vec<String> {
|
||||
let mut out = Vec::new();
|
||||
let mut visited = FxHashSet::default();
|
||||
let mut work = VecDeque::new();
|
||||
|
|
@ -2565,7 +2565,7 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> {
|
|||
work.push_back(first_ty);
|
||||
|
||||
while let Some(ty) = work.pop_front() {
|
||||
if !visited.insert(ty.clone()) {
|
||||
if !visited.insert(ty) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -2575,16 +2575,16 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> {
|
|||
work.extend(tys.into_iter());
|
||||
}
|
||||
clean::Type::Slice(ty) => {
|
||||
work.push_back(*ty);
|
||||
work.push_back(ty);
|
||||
}
|
||||
clean::Type::Array(ty, _) => {
|
||||
work.push_back(*ty);
|
||||
work.push_back(ty);
|
||||
}
|
||||
clean::Type::RawPointer(_, ty) => {
|
||||
work.push_back(*ty);
|
||||
work.push_back(ty);
|
||||
}
|
||||
clean::Type::BorrowedRef { type_, .. } => {
|
||||
work.push_back(*type_);
|
||||
work.push_back(type_);
|
||||
}
|
||||
clean::Type::QPath(box clean::QPathData { self_type, trait_, .. }) => {
|
||||
work.push_back(self_type);
|
||||
|
|
|
|||
|
|
@ -413,7 +413,7 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
|
|||
|
||||
match myitem.kind {
|
||||
clean::ExternCrateItem { ref src } => {
|
||||
use crate::html::format::anchor;
|
||||
use crate::html::format::print_anchor;
|
||||
|
||||
match *src {
|
||||
Some(src) => {
|
||||
|
|
@ -421,7 +421,7 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
|
|||
w,
|
||||
"<dt><code>{}extern crate {} as {};",
|
||||
visibility_print_with_space(myitem, cx),
|
||||
anchor(myitem.item_id.expect_def_id(), src, cx),
|
||||
print_anchor(myitem.item_id.expect_def_id(), src, cx),
|
||||
EscapeBodyTextWithWbr(myitem.name.unwrap().as_str())
|
||||
)?;
|
||||
}
|
||||
|
|
@ -430,7 +430,11 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
|
|||
w,
|
||||
"<dt><code>{}extern crate {};",
|
||||
visibility_print_with_space(myitem, cx),
|
||||
anchor(myitem.item_id.expect_def_id(), myitem.name.unwrap(), cx)
|
||||
print_anchor(
|
||||
myitem.item_id.expect_def_id(),
|
||||
myitem.name.unwrap(),
|
||||
cx
|
||||
)
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
|
@ -439,7 +443,7 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
|
|||
|
||||
clean::ImportItem(ref import) => {
|
||||
let stab_tags = import.source.did.map_or_else(String::new, |import_def_id| {
|
||||
extra_info_tags(tcx, myitem, item, Some(import_def_id)).to_string()
|
||||
print_extra_info_tags(tcx, myitem, item, Some(import_def_id)).to_string()
|
||||
});
|
||||
|
||||
let id = match import.kind {
|
||||
|
|
@ -497,7 +501,9 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
|
|||
write!(
|
||||
w,
|
||||
"<dt>\
|
||||
<a class=\"{class}\" href=\"{href}\" title=\"{title}\">{name}</a>\
|
||||
<a class=\"{class}\" href=\"{href}\" title=\"{title1} {title2}\">\
|
||||
{name}\
|
||||
</a>\
|
||||
{visibility_and_hidden}\
|
||||
{unsafety_flag}\
|
||||
{stab_tags}\
|
||||
|
|
@ -505,11 +511,12 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
|
|||
{docs_before}{docs}{docs_after}",
|
||||
name = EscapeBodyTextWithWbr(myitem.name.unwrap().as_str()),
|
||||
visibility_and_hidden = visibility_and_hidden,
|
||||
stab_tags = extra_info_tags(tcx, myitem, item, None),
|
||||
stab_tags = print_extra_info_tags(tcx, myitem, item, None),
|
||||
class = myitem.type_(),
|
||||
unsafety_flag = unsafety_flag,
|
||||
href = item_path(myitem.type_(), myitem.name.unwrap().as_str()),
|
||||
title = format_args!("{} {}", myitem.type_(), full_path(cx, myitem)),
|
||||
href = print_item_path(myitem.type_(), myitem.name.unwrap().as_str()),
|
||||
title1 = myitem.type_(),
|
||||
title2 = full_path(cx, myitem),
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
|
@ -524,7 +531,7 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
|
|||
|
||||
/// Render the stability, deprecation and portability tags that are displayed in the item's summary
|
||||
/// at the module level.
|
||||
fn extra_info_tags(
|
||||
fn print_extra_info_tags(
|
||||
tcx: TyCtxt<'_>,
|
||||
item: &clean::Item,
|
||||
parent: &clean::Item,
|
||||
|
|
@ -639,7 +646,7 @@ fn item_function(cx: &Context<'_>, it: &clean::Item, f: &clean::Function) -> imp
|
|||
fn item_trait(cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) -> impl fmt::Display {
|
||||
fmt::from_fn(|w| {
|
||||
let tcx = cx.tcx();
|
||||
let bounds = bounds(&t.bounds, false, cx);
|
||||
let bounds = print_bounds(&t.bounds, false, cx);
|
||||
let required_types =
|
||||
t.items.iter().filter(|m| m.is_required_associated_type()).collect::<Vec<_>>();
|
||||
let provided_types = t.items.iter().filter(|m| m.is_associated_type()).collect::<Vec<_>>();
|
||||
|
|
@ -652,7 +659,7 @@ fn item_trait(cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) -> impl fmt:
|
|||
let count_types = required_types.len() + provided_types.len();
|
||||
let count_consts = required_consts.len() + provided_consts.len();
|
||||
let count_methods = required_methods.len() + provided_methods.len();
|
||||
let must_implement_one_of_functions = tcx.trait_def(t.def_id).must_implement_one_of.clone();
|
||||
let must_implement_one_of_functions = &tcx.trait_def(t.def_id).must_implement_one_of;
|
||||
|
||||
// Output the trait definition
|
||||
wrap_item(w, |mut w| {
|
||||
|
|
@ -1088,7 +1095,7 @@ fn item_trait(cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) -> impl fmt:
|
|||
it,
|
||||
&implementor_dups,
|
||||
&collect_paths_for_type(
|
||||
implementor.inner_impl().for_.clone(),
|
||||
&implementor.inner_impl().for_,
|
||||
&cx.shared.cache,
|
||||
),
|
||||
)
|
||||
|
|
@ -1236,7 +1243,7 @@ fn item_trait_alias(
|
|||
attrs = render_attributes_in_pre(it, "", cx),
|
||||
name = it.name.unwrap(),
|
||||
generics = t.generics.print(cx),
|
||||
bounds = bounds(&t.bounds, true, cx),
|
||||
bounds = print_bounds(&t.bounds, true, cx),
|
||||
where_clause =
|
||||
print_where_clause(&t.generics, cx, 0, Ending::NoNewline).maybe_display(),
|
||||
)
|
||||
|
|
@ -2254,14 +2261,18 @@ pub(super) fn full_path(cx: &Context<'_>, item: &clean::Item) -> String {
|
|||
s
|
||||
}
|
||||
|
||||
pub(super) fn item_path(ty: ItemType, name: &str) -> impl Display {
|
||||
pub(super) fn print_item_path(ty: ItemType, name: &str) -> impl Display {
|
||||
fmt::from_fn(move |f| match ty {
|
||||
ItemType::Module => write!(f, "{}index.html", ensure_trailing_slash(name)),
|
||||
_ => write!(f, "{ty}.{name}.html"),
|
||||
})
|
||||
}
|
||||
|
||||
fn bounds(bounds: &[clean::GenericBound], trait_alias: bool, cx: &Context<'_>) -> impl Display {
|
||||
fn print_bounds(
|
||||
bounds: &[clean::GenericBound],
|
||||
trait_alias: bool,
|
||||
cx: &Context<'_>,
|
||||
) -> impl Display {
|
||||
(!bounds.is_empty())
|
||||
.then_some(fmt::from_fn(move |f| {
|
||||
let has_lots_of_bounds = bounds.len() > 2;
|
||||
|
|
|
|||
|
|
@ -607,16 +607,9 @@ impl TypeAliasPart {
|
|||
let cx = type_impl_collector.cx;
|
||||
let aliased_types = type_impl_collector.aliased_types;
|
||||
for aliased_type in aliased_types.values() {
|
||||
let impls = aliased_type
|
||||
.impl_
|
||||
.values()
|
||||
.flat_map(|AliasedTypeImpl { impl_, type_aliases }| {
|
||||
let mut ret: Vec<AliasSerializableImpl> = Vec::new();
|
||||
let trait_ = impl_
|
||||
.inner_impl()
|
||||
.trait_
|
||||
.as_ref()
|
||||
.map(|trait_| format!("{:#}", trait_.print(cx)));
|
||||
let impls = aliased_type.impl_.values().filter_map(
|
||||
|AliasedTypeImpl { impl_, type_aliases }| {
|
||||
let mut ret: Option<AliasSerializableImpl> = None;
|
||||
// render_impl will filter out "impossible-to-call" methods
|
||||
// to make that functionality work here, it needs to be called with
|
||||
// each type alias, and if it gives a different result, split the impl
|
||||
|
|
@ -624,8 +617,8 @@ impl TypeAliasPart {
|
|||
cx.id_map.borrow_mut().clear();
|
||||
cx.deref_id_map.borrow_mut().clear();
|
||||
let type_alias_fqp = (*type_alias_fqp).iter().join("::");
|
||||
if let Some(last) = ret.last_mut() {
|
||||
last.aliases.push(type_alias_fqp);
|
||||
if let Some(ret) = &mut ret {
|
||||
ret.aliases.push(type_alias_fqp);
|
||||
} else {
|
||||
let target_did = impl_
|
||||
.inner_impl()
|
||||
|
|
@ -660,16 +653,22 @@ impl TypeAliasPart {
|
|||
},
|
||||
)
|
||||
.to_string();
|
||||
ret.push(AliasSerializableImpl {
|
||||
// The alternate display prints it as plaintext instead of HTML.
|
||||
let trait_ = impl_
|
||||
.inner_impl()
|
||||
.trait_
|
||||
.as_ref()
|
||||
.map(|trait_| format!("{:#}", trait_.print(cx)));
|
||||
ret = Some(AliasSerializableImpl {
|
||||
text,
|
||||
trait_: trait_.clone(),
|
||||
trait_,
|
||||
aliases: vec![type_alias_fqp],
|
||||
})
|
||||
}
|
||||
}
|
||||
ret
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
},
|
||||
);
|
||||
|
||||
let mut path = PathBuf::from("type.impl");
|
||||
for component in &aliased_type.target_fqp[..aliased_type.target_fqp.len() - 1] {
|
||||
|
|
@ -682,7 +681,7 @@ impl TypeAliasPart {
|
|||
));
|
||||
|
||||
let part = OrderedJson::array_sorted(
|
||||
impls.iter().map(OrderedJson::serialize).collect::<Result<Vec<_>, _>>().unwrap(),
|
||||
impls.map(|impl_| OrderedJson::serialize(impl_).unwrap()),
|
||||
);
|
||||
path_parts.push(path, OrderedJson::array_unsorted([crate_name_json, &part]));
|
||||
}
|
||||
|
|
@ -760,7 +759,7 @@ impl TraitAliasPart {
|
|||
Some(Implementor {
|
||||
text: imp.inner_impl().print(false, cx).to_string(),
|
||||
synthetic: imp.inner_impl().kind.is_auto(),
|
||||
types: collect_paths_for_type(imp.inner_impl().for_.clone(), cache),
|
||||
types: collect_paths_for_type(&imp.inner_impl().for_, cache),
|
||||
})
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,51 +1,51 @@
|
|||
use rustc_span::{Symbol, sym};
|
||||
use rustc_span::{Symbol, create_default_session_globals_then, sym};
|
||||
|
||||
use crate::html::format::href_relative_parts;
|
||||
|
||||
fn assert_relative_path(expected: &[Symbol], relative_to_fqp: &[Symbol], fqp: &[Symbol]) {
|
||||
// No `create_default_session_globals_then` call is needed here because all
|
||||
// the symbols used are static, and no `Symbol::intern` calls occur.
|
||||
assert_eq!(expected, href_relative_parts(&fqp, &relative_to_fqp).collect::<Vec<_>>());
|
||||
fn assert_relative_path(expected: &str, relative_to_fqp: &[Symbol], fqp: &[Symbol]) {
|
||||
create_default_session_globals_then(|| {
|
||||
assert_eq!(expected, href_relative_parts(&fqp, &relative_to_fqp).finish());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn href_relative_parts_basic() {
|
||||
let relative_to_fqp = &[sym::std, sym::vec];
|
||||
let fqp = &[sym::std, sym::iter];
|
||||
assert_relative_path(&[sym::dotdot, sym::iter], relative_to_fqp, fqp);
|
||||
assert_relative_path("../iter", relative_to_fqp, fqp);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn href_relative_parts_parent_module() {
|
||||
let relative_to_fqp = &[sym::std, sym::vec];
|
||||
let fqp = &[sym::std];
|
||||
assert_relative_path(&[sym::dotdot], relative_to_fqp, fqp);
|
||||
assert_relative_path("..", relative_to_fqp, fqp);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn href_relative_parts_different_crate() {
|
||||
let relative_to_fqp = &[sym::std, sym::vec];
|
||||
let fqp = &[sym::core, sym::iter];
|
||||
assert_relative_path(&[sym::dotdot, sym::dotdot, sym::core, sym::iter], relative_to_fqp, fqp);
|
||||
assert_relative_path("../../core/iter", relative_to_fqp, fqp);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn href_relative_parts_same_module() {
|
||||
let relative_to_fqp = &[sym::std, sym::vec];
|
||||
let fqp = &[sym::std, sym::vec];
|
||||
assert_relative_path(&[], relative_to_fqp, fqp);
|
||||
assert_relative_path("", relative_to_fqp, fqp);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn href_relative_parts_child_module() {
|
||||
let relative_to_fqp = &[sym::std];
|
||||
let fqp = &[sym::std, sym::vec];
|
||||
assert_relative_path(&[sym::vec], relative_to_fqp, fqp);
|
||||
assert_relative_path("vec", relative_to_fqp, fqp);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn href_relative_parts_root() {
|
||||
let relative_to_fqp = &[];
|
||||
let fqp = &[sym::std];
|
||||
assert_relative_path(&[sym::std], relative_to_fqp, fqp);
|
||||
assert_relative_path("std", relative_to_fqp, fqp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ pub(crate) struct UrlPartsBuilder {
|
|||
|
||||
impl UrlPartsBuilder {
|
||||
/// Create an empty buffer.
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn new() -> Self {
|
||||
Self { buf: String::new() }
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue