From 37d363879e9dbc60969b297a99220e7928cb28a9 Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Mon, 30 May 2022 22:53:59 -0700 Subject: [PATCH] Improve calculation of "Impls on Foreign Types" --- src/librustdoc/formats/mod.rs | 25 ++++++++++++++++++++++++ src/librustdoc/html/render/mod.rs | 4 +--- src/librustdoc/html/render/print_item.rs | 5 ++--- src/test/rustdoc/issue-75588.rs | 2 +- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/formats/mod.rs b/src/librustdoc/formats/mod.rs index 3e36318eb71b0..53cc11ba482ef 100644 --- a/src/librustdoc/formats/mod.rs +++ b/src/librustdoc/formats/mod.rs @@ -7,6 +7,7 @@ use rustc_hir::def_id::DefId; crate use renderer::{run_format, FormatRenderer}; use crate::clean::{self, ItemId}; +use cache::Cache; /// Specifies whether rendering directly implemented trait items or ones from a certain Deref /// impl. @@ -60,4 +61,28 @@ impl Impl { } } } + + // Returns true if this is an implementation on a "local" type, meaning: + // the type is in the current crate, or the type and the trait are both + // re-exported by the current crate. + pub(crate) fn is_on_local_type(&self, cache: &Cache) -> bool { + let for_type = &self.inner_impl().for_; + if let Some(for_type_did) = for_type.def_id(cache) { + // The "for" type is local if it's in the paths for the current crate. + if cache.paths.contains_key(&for_type_did) { + return true; + } + if let Some(trait_did) = self.trait_did() { + // The "for" type and the trait are from the same crate. That could + // be different from the current crate, for instance when both were + // re-exported from some other crate. But they are local with respect to + // each other. + if for_type_did.krate == trait_did.krate { + return true; + } + } + return false; + }; + true + } } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index c13ae1e431a6c..c21add68d2cff 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2287,9 +2287,7 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean if let Some(implementors) = cache.implementors.get(&it.item_id.expect_def_id()) { let mut res = implementors .iter() - .filter(|i| { - i.inner_impl().for_.def_id(cache).map_or(false, |d| !cache.paths.contains_key(&d)) - }) + .filter(|i| !i.is_on_local_type(cache)) .filter_map(|i| extract_for_impl_name(&i.impl_item, cx)) .collect::>(); diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 4951cd83af207..363b38add0518 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -818,9 +818,8 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra } } - let (local, foreign) = implementors.iter().partition::, _>(|i| { - i.inner_impl().for_.def_id(cache).map_or(true, |d| cache.paths.contains_key(&d)) - }); + let (local, foreign) = + implementors.iter().partition::, _>(|i| i.is_on_local_type(cache)); let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) = local.iter().partition(|i| i.inner_impl().kind.is_auto()); diff --git a/src/test/rustdoc/issue-75588.rs b/src/test/rustdoc/issue-75588.rs index ac97b94fb351b..a8cb16ec34cc0 100644 --- a/src/test/rustdoc/issue-75588.rs +++ b/src/test/rustdoc/issue-75588.rs @@ -13,5 +13,5 @@ extern crate real_gimli; // @!has foo/trait.Deref.html '//*[@id="impl-Deref-for-EndianSlice"]//h3[@class="code-header in-band"]' 'impl Deref for EndianSlice' pub use realcore::Deref; -// @has foo/trait.Join.html '//*[@id="impl-Join-for-Foo"]//h3[@class="code-header in-band"]' 'impl Join for Foo' +// @has foo/trait.Join.html '//*[@id="impl-Join"]//h3[@class="code-header in-band"]' 'impl Join for Foo' pub use realcore::Join;