diff --git a/src/librustdoc/formats/mod.rs b/src/librustdoc/formats/mod.rs index 9f26ccc74d1..b236bd7be4f 100644 --- a/src/librustdoc/formats/mod.rs +++ b/src/librustdoc/formats/mod.rs @@ -7,7 +7,7 @@ use rustc_hir::def_id::DefId; pub(crate) use renderer::{run_format, FormatRenderer}; use crate::clean::{self, ItemId}; -use cache::Cache; +use crate::html::render::Context; /// Specifies whether rendering directly implemented trait items or ones from a certain Deref /// impl. @@ -65,7 +65,8 @@ 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 { + pub(crate) fn is_on_local_type(&self, cx: &Context<'_>) -> bool { + let cache = cx.cache(); 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. @@ -80,6 +81,18 @@ impl Impl { if for_type_did.krate == trait_did.krate { return true; } + // Hack: many traits and types in std are re-exported from + // core or alloc. In general, rustdoc is capable of recognizing + // these implementations as being on local types. However, in at + // least one case (https://github.com/rust-lang/rust/issues/97610), + // rustdoc gets confused and labels an implementation as being on + // a foreign type. To make sure that confusion doesn't pass on to + // the reader, consider all implementations in std, core, and alloc + // to be on local types. + let crate_name = cx.tcx().crate_name(trait_did.krate); + if matches!(crate_name.as_str(), "std" | "core" | "alloc") { + return true; + } } return false; }; diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 0b801a20995..23ce634cf28 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2281,11 +2281,10 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean |sym| format!("{0}", sym, ItemType::Method), ); - let cache = cx.cache(); - if let Some(implementors) = cache.implementors.get(&it.item_id.expect_def_id()) { + if let Some(implementors) = cx.cache().implementors.get(&it.item_id.expect_def_id()) { let mut res = implementors .iter() - .filter(|i| !i.is_on_local_type(cache)) + .filter(|i| !i.is_on_local_type(cx)) .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 8683e6dfcd9..d115185562c 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -823,7 +823,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } let (local, foreign) = - implementors.iter().partition::, _>(|i| i.is_on_local_type(cache)); + implementors.iter().partition::, _>(|i| i.is_on_local_type(cx)); let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) = local.iter().partition(|i| i.inner_impl().kind.is_auto());