diff options
Diffstat (limited to 'src/librustdoc')
| -rw-r--r-- | src/librustdoc/html/render/context.rs | 10 | ||||
| -rw-r--r-- | src/librustdoc/html/render/mod.rs | 30 | ||||
| -rw-r--r-- | src/librustdoc/passes/collect_trait_impls.rs | 101 |
3 files changed, 44 insertions, 97 deletions
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 864fbccbcc4..1d90122af15 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -5,8 +5,7 @@ use std::path::PathBuf; use std::rc::Rc; use std::sync::mpsc::channel; -use rustc_data_structures::fx::FxHashMap; -use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_hir::def_id::{LOCAL_CRATE}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_span::edition::Edition; @@ -53,9 +52,6 @@ crate struct Context<'tcx> { pub(super) render_redirect_pages: bool, /// The map used to ensure all generated 'id=' attributes are unique. pub(super) id_map: RefCell<IdMap>, - /// Tracks section IDs for `Deref` targets so they match in both the main - /// body and the sidebar. - pub(super) deref_id_map: RefCell<FxHashMap<DefId, String>>, /// Shared mutable state. /// /// Issue for improving the situation: [#82381][] @@ -76,7 +72,7 @@ crate struct Context<'tcx> { // `Context` is cloned a lot, so we don't want the size to grow unexpectedly. #[cfg(target_arch = "x86_64")] -rustc_data_structures::static_assert_size!(Context<'_>, 152); +rustc_data_structures::static_assert_size!(Context<'_>, 112); impl<'tcx> Context<'tcx> { pub(super) fn path(&self, filename: &str) -> PathBuf { @@ -416,7 +412,6 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { dst, render_redirect_pages: false, id_map: RefCell::new(id_map), - deref_id_map: RefCell::new(FxHashMap::default()), shared: Rc::new(scx), cache: Rc::new(cache), }; @@ -439,7 +434,6 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { dst: self.dst.clone(), render_redirect_pages: self.render_redirect_pages, id_map: RefCell::new(id_map), - deref_id_map: RefCell::new(FxHashMap::default()), shared: Rc::clone(&self.shared), cache: Rc::clone(&self.cache), } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 66c47f14655..820a5098bb4 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1159,21 +1159,12 @@ fn render_assoc_items( RenderMode::Normal } AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => { - let id = cx.derive_id(small_url_encode(format!( - "deref-methods-{:#}", - type_.print(cx.cache()) - ))); - debug!("Adding {} to deref id map", type_.print(cx.cache())); - cx.deref_id_map - .borrow_mut() - .insert(type_.def_id_full(cx.cache()).unwrap(), id.clone()); write!( w, - "<h2 id=\"{id}\" class=\"small-section-header\">\ + "<h2 id=\"deref-methods\" class=\"small-section-header\">\ Methods from {trait_}<Target = {type_}>\ - <a href=\"#{id}\" class=\"anchor\"></a>\ + <a href=\"#deref-methods\" class=\"anchor\"></a>\ </h2>", - id = id, trait_ = trait_.print(cx.cache()), type_ = type_.print(cx.cache()), ); @@ -1198,6 +1189,9 @@ fn render_assoc_items( ); } } + if let AssocItemRender::DerefFor { .. } = what { + return; + } if !traits.is_empty() { let deref_impl = traits .iter() @@ -1208,13 +1202,6 @@ fn render_assoc_items( }); render_deref_methods(w, cx, impl_, containing_item, has_deref_mut); } - - // If we were already one level into rendering deref methods, we don't want to render - // anything after recursing into any further deref methods above. - if let AssocItemRender::DerefFor { .. } = what { - return; - } - let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) = traits.iter().partition(|t| t.inner_impl().synthetic); let (blanket_impl, concrete): (Vec<&&Impl>, _) = @@ -2020,14 +2007,9 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V .flat_map(|i| get_methods(i.inner_impl(), true, &mut used_links, deref_mut, c)) .collect::<Vec<_>>(); if !ret.is_empty() { - let deref_id_map = cx.deref_id_map.borrow(); - let id = deref_id_map - .get(&real_target.def_id_full(cx.cache()).unwrap()) - .expect("Deref section without derived id"); write!( out, - "<a class=\"sidebar-title\" href=\"#{}\">Methods from {}<Target={}></a>", - id, + "<a class=\"sidebar-title\" href=\"#deref-methods\">Methods from {}<Target={}></a>", Escape(&format!("{:#}", impl_.inner_impl().trait_.as_ref().unwrap().print(c))), Escape(&format!("{:#}", real_target.print(c))), ); diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 685451b87ed..492cc9118fe 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -3,7 +3,7 @@ use crate::clean::*; use crate::core::DocContext; use crate::fold::DocFolder; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashSet}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::ty::DefIdTree; use rustc_span::symbol::sym; @@ -53,6 +53,39 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate { } } + let mut cleaner = BadImplStripper { prims, items: crate_items }; + + // scan through included items ahead of time to splice in Deref targets to the "valid" sets + for it in &new_items { + if let ImplItem(Impl { ref for_, ref trait_, ref items, .. }) = *it.kind { + if cleaner.keep_impl(for_) && trait_.def_id() == cx.tcx.lang_items().deref_trait() { + let target = items + .iter() + .find_map(|item| match *item.kind { + TypedefItem(ref t, true) => Some(&t.type_), + _ => None, + }) + .expect("Deref impl without Target type"); + + if let Some(prim) = target.primitive_type() { + cleaner.prims.insert(prim); + } else if let Some(did) = target.def_id() { + cleaner.items.insert(did); + } + } + } + } + + new_items.retain(|it| { + if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = *it.kind { + cleaner.keep_impl(for_) + || trait_.as_ref().map_or(false, |t| cleaner.keep_impl(t)) + || blanket_impl.is_some() + } else { + true + } + }); + // `tcx.crates()` doesn't include the local crate, and `tcx.all_trait_implementations` // doesn't work with it anyway, so pull them from the HIR map instead let mut extra_attrs = Vec::new(); @@ -84,53 +117,6 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate { } } - let mut cleaner = BadImplStripper { prims, items: crate_items }; - - let mut type_did_to_deref_target: FxHashMap<DefId, &Type> = FxHashMap::default(); - // Gather all type to `Deref` target edges. - for it in &new_items { - if let ImplItem(Impl { ref for_, ref trait_, ref items, .. }) = *it.kind { - if trait_.def_id() == cx.tcx.lang_items().deref_trait() { - let target = items.iter().find_map(|item| match *item.kind { - TypedefItem(ref t, true) => Some(&t.type_), - _ => None, - }); - if let (Some(for_did), Some(target)) = (for_.def_id(), target) { - type_did_to_deref_target.insert(for_did, target); - } - } - } - } - // Follow all `Deref` targets of included items and recursively add them as valid - fn add_deref_target( - map: &FxHashMap<DefId, &Type>, - cleaner: &mut BadImplStripper, - type_did: &DefId, - ) { - if let Some(target) = map.get(type_did) { - debug!("add_deref_target: type {:?}, target {:?}", type_did, target); - if let Some(target_prim) = target.primitive_type() { - cleaner.prims.insert(target_prim); - } else if let Some(target_did) = target.def_id() { - // `impl Deref<Target = S> for S` - if target_did == *type_did { - // Avoid infinite cycles - return; - } - cleaner.items.insert(target_did); - add_deref_target(map, cleaner, &target_did); - } - } - } - for type_did in type_did_to_deref_target.keys() { - // Since only the `DefId` portion of the `Type` instances is known to be same for both the - // `Deref` target type and the impl for type positions, this map of types is keyed by - // `DefId` and for convenience uses a special cleaner that accepts `DefId`s directly. - if cleaner.keep_impl_with_def_id(type_did) { - add_deref_target(&type_did_to_deref_target, &mut cleaner, type_did); - } - } - let items = if let Some(ref mut it) = krate.module { if let ModuleItem(Module { ref mut items, .. }) = *it.kind { items @@ -142,18 +128,7 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate { }; items.extend(synth_impls); - for it in new_items.drain(..) { - if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = *it.kind { - if !(cleaner.keep_impl(for_) - || trait_.as_ref().map_or(false, |t| cleaner.keep_impl(t)) - || blanket_impl.is_some()) - { - continue; - } - } - - items.push(it); - } + items.extend(new_items); krate } @@ -208,13 +183,9 @@ impl BadImplStripper { } else if let Some(prim) = ty.primitive_type() { self.prims.contains(&prim) } else if let Some(did) = ty.def_id() { - self.keep_impl_with_def_id(&did) + self.items.contains(&did) } else { false } } - - fn keep_impl_with_def_id(&self, did: &DefId) -> bool { - self.items.contains(did) - } } |
