about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-02-18 10:26:45 +0000
committerbors <bors@rust-lang.org>2022-02-18 10:26:45 +0000
commitb8c56fa8c30821129b0960180f528d4a1a4f9316 (patch)
treee10393af81501f8642b144aa256686d77d6a78f9
parentfeac2ecf1cae1dd0f56bed1cecc6e109c64b3d4f (diff)
parent0da7adc8283211ffc649d169a94deed20f331c81 (diff)
downloadrust-b8c56fa8c30821129b0960180f528d4a1a4f9316.tar.gz
rust-b8c56fa8c30821129b0960180f528d4a1a4f9316.zip
Auto merge of #93766 - petrochenkov:doclinkregr, r=camelid,GuillaumeGomez
rustdoc: Collect traits in scope for lang items

Inherent impls on primitive types are not included in the list of all inherent impls in the crate (`inherent_impls_in_crate_untracked`), they are taken from the list of lang items instead, but such impls can also be inlined by rustdoc, e.g. if something derefs to a primitive type.

r? `@camelid`
Fixes https://github.com/rust-lang/rust/issues/93698
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs12
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs7
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links/early.rs4
-rw-r--r--src/test/rustdoc/intra-doc/auxiliary/extern-lang-item-impl-dep.rs29
-rw-r--r--src/test/rustdoc/intra-doc/extern-lang-item-impl.rs11
5 files changed, 55 insertions, 8 deletions
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 87a88fbac71..66968c9ba54 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1032,13 +1032,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     /// Iterates over the language items in the given crate.
-    fn get_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] {
-        tcx.arena.alloc_from_iter(
-            self.root
-                .lang_items
-                .decode(self)
-                .map(|(def_index, index)| (self.local_def_id(def_index), index)),
-        )
+    fn get_lang_items(self) -> impl Iterator<Item = (DefId, usize)> + 'a {
+        self.root
+            .lang_items
+            .decode(self)
+            .map(move |(def_index, index)| (self.local_def_id(def_index), index))
     }
 
     /// Iterates over the diagnostic items in the given crate.
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 9b0272e7fd3..7708b5193f4 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -200,7 +200,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
         tcx.arena.alloc_slice(&result)
     }
     defined_lib_features => { cdata.get_lib_features(tcx) }
-    defined_lang_items => { cdata.get_lang_items(tcx) }
+    defined_lang_items => { tcx.arena.alloc_from_iter(cdata.get_lang_items()) }
     diagnostic_items => { cdata.get_diagnostic_items() }
     missing_lang_items => { cdata.get_missing_lang_items(tcx) }
 
@@ -501,6 +501,11 @@ impl CStore {
     ) -> impl Iterator<Item = (DefId, DefId)> + '_ {
         self.get_crate_data(cnum).get_inherent_impls()
     }
+
+    /// Decodes all lang items in the crate (for rustdoc).
+    pub fn lang_items_untracked(&self, cnum: CrateNum) -> impl Iterator<Item = DefId> + '_ {
+        self.get_crate_data(cnum).get_lang_items().map(|(def_id, _)| def_id)
+    }
 }
 
 impl CrateStore for CStore {
diff --git a/src/librustdoc/passes/collect_intra_doc_links/early.rs b/src/librustdoc/passes/collect_intra_doc_links/early.rs
index e28034b2b0d..5c11ab1d3be 100644
--- a/src/librustdoc/passes/collect_intra_doc_links/early.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links/early.rs
@@ -118,6 +118,7 @@ impl IntraLinkCrateLoader<'_, '_> {
                 Vec::from_iter(self.resolver.cstore().trait_impls_in_crate_untracked(cnum));
             let all_inherent_impls =
                 Vec::from_iter(self.resolver.cstore().inherent_impls_in_crate_untracked(cnum));
+            let all_lang_items = Vec::from_iter(self.resolver.cstore().lang_items_untracked(cnum));
 
             // Querying traits in scope is expensive so we try to prune the impl and traits lists
             // using privacy, private traits and impls from other crates are never documented in
@@ -141,6 +142,9 @@ impl IntraLinkCrateLoader<'_, '_> {
                     self.add_traits_in_parent_scope(impl_def_id);
                 }
             }
+            for def_id in all_lang_items {
+                self.add_traits_in_parent_scope(def_id);
+            }
 
             self.all_traits.extend(all_traits);
             self.all_trait_impls.extend(all_trait_impls.into_iter().map(|(_, def_id, _)| def_id));
diff --git a/src/test/rustdoc/intra-doc/auxiliary/extern-lang-item-impl-dep.rs b/src/test/rustdoc/intra-doc/auxiliary/extern-lang-item-impl-dep.rs
new file mode 100644
index 00000000000..87ae2f096bb
--- /dev/null
+++ b/src/test/rustdoc/intra-doc/auxiliary/extern-lang-item-impl-dep.rs
@@ -0,0 +1,29 @@
+// no-prefer-dynamic
+
+#![feature(lang_items)]
+
+#![crate_type = "rlib"]
+#![no_std]
+
+pub struct DerefsToF64(f64);
+
+impl core::ops::Deref for DerefsToF64 {
+    type Target = f64;
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+mod inner {
+    #[lang = "f64_runtime"]
+    impl f64 {
+        /// [f64::clone]
+        pub fn method() {}
+    }
+}
+
+#[lang = "eh_personality"]
+fn foo() {}
+
+#[panic_handler]
+fn bar(_: &core::panic::PanicInfo) -> ! { loop {} }
diff --git a/src/test/rustdoc/intra-doc/extern-lang-item-impl.rs b/src/test/rustdoc/intra-doc/extern-lang-item-impl.rs
new file mode 100644
index 00000000000..f64f886f076
--- /dev/null
+++ b/src/test/rustdoc/intra-doc/extern-lang-item-impl.rs
@@ -0,0 +1,11 @@
+// Reexport of a structure that derefs to a type with lang item impls having doc links in their
+// comments. The doc link points to an associated item, so we check that traits in scope for that
+// link are populated.
+
+// aux-build:extern-lang-item-impl-dep.rs
+
+#![no_std]
+
+extern crate extern_lang_item_impl_dep;
+
+pub use extern_lang_item_impl_dep::DerefsToF64;