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());