diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 07ecd98f77596..d27f0b9d00675 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -106,7 +106,7 @@ impl From 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. @@ -1601,9 +1601,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. @@ -1676,7 +1674,7 @@ impl Type { } } - pub(crate) fn generics(&self) -> Option> { + pub(crate) fn generics<'a>(&'a self) -> Option> { match self { Type::Path { path, .. } => path.generics(), _ => None, @@ -2234,17 +2232,13 @@ impl Path { self.segments.last().map(|seg| &seg.args) } - pub(crate) fn generics(&self) -> Option> { + pub(crate) fn generics<'a>(&'a self) -> Option> { 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 } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 486d4ae932d97..e9a7f4367a387 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -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), 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 + '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, 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(()) }) } diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 3b5f9b5a45897..50320cb231d2f 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -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, diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index ad7dfafd90c7d..d6ad3545b6951 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -195,7 +195,7 @@ fn slugify(c: char) -> Option { } } -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct Playground { pub crate_name: Option, pub url: String, diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 1f7201b8ca8b2..5984dcd74caf9 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -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)?; diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 06cb9269cc87f..dd6b58adf5212 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2530,7 +2530,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 { +fn collect_paths_for_type(first_ty: &clean::Type, cache: &Cache) -> Vec { let mut out = Vec::new(); let mut visited = FxHashSet::default(); let mut work = VecDeque::new(); @@ -2547,7 +2547,7 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec { work.push_back(first_ty); while let Some(ty) = work.pop_front() { - if !visited.insert(ty.clone()) { + if !visited.insert(ty) { continue; } @@ -2557,16 +2557,16 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec { 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); diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 39a631b637bd4..fa3347c65d3fc 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -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, "
{}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, "
{}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, "
\ - {name}\ + \ + {name}\ + \ {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::>(); let provided_types = t.items.iter().filter(|m| m.is_associated_type()).collect::>(); @@ -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(), ) @@ -2185,14 +2192,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; diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 4f6e9abdbca06..33738f7a242f6 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -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 = 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 = 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::>(); + }, + ); 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::, _>>().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), }) } }) diff --git a/src/librustdoc/html/tests.rs b/src/librustdoc/html/tests.rs index b568942bbcb9b..873462bbeba8f 100644 --- a/src/librustdoc/html/tests.rs +++ b/src/librustdoc/html/tests.rs @@ -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::>()); +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); } diff --git a/src/librustdoc/html/url_parts_builder.rs b/src/librustdoc/html/url_parts_builder.rs index 1e6af6af63cc4..9a53382744154 100644 --- a/src/librustdoc/html/url_parts_builder.rs +++ b/src/librustdoc/html/url_parts_builder.rs @@ -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() } }