summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-05-16 20:12:18 +0200
committerGitHub <noreply@github.com>2023-05-16 20:12:18 +0200
commit54a49769fa106b0732dcc15f68e59f4a07ffa909 (patch)
treed81d0b9f8453087104e288cfc4872b4ef9a8a665
parentd2e52ea127fea8d3c8eef3815cb52935f85605a3 (diff)
parent0f1d4b5d4d46687130cbd2766ab1d761bdac90c4 (diff)
downloadrust-54a49769fa106b0732dcc15f68e59f4a07ffa909.tar.gz
Rollup merge of #111642 - GuillaumeGomez:only-impl-from-bodies, r=notriddle
[rustdoc] Only keep impl blocks from bodies Fixes https://github.com/rust-lang/rust/issues/111415. The problem was that we kept everything inside bodies whereas only impl blocks are actually accessible from outside bodies. r? `@notriddle`
-rw-r--r--src/librustdoc/visit_ast.rs30
-rw-r--r--tests/rustdoc/nested-items-issue-111415.rs36
2 files changed, 65 insertions, 1 deletions
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index ff13daa6db4..8f8dc6b7090 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -5,7 +5,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LocalDefIdSet};
-use rustc_hir::intravisit::{walk_item, Visitor};
+use rustc_hir::intravisit::{walk_body, walk_item, Visitor};
use rustc_hir::{Node, CRATE_HIR_ID};
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::TyCtxt;
@@ -106,6 +106,7 @@ pub(crate) struct RustdocVisitor<'a, 'tcx> {
exact_paths: DefIdMap<Vec<Symbol>>,
modules: Vec<Module<'tcx>>,
is_importable_from_parent: bool,
+ inside_body: bool,
}
impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
@@ -129,6 +130,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
exact_paths: Default::default(),
modules: vec![om],
is_importable_from_parent: true,
+ inside_body: false,
}
}
@@ -368,6 +370,26 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
import_id: Option<LocalDefId>,
) {
debug!("visiting item {:?}", item);
+ if self.inside_body {
+ // Only impls can be "seen" outside a body. For example:
+ //
+ // ```
+ // struct Bar;
+ //
+ // fn foo() {
+ // impl Bar { fn bar() {} }
+ // }
+ // Bar::bar();
+ // ```
+ if let hir::ItemKind::Impl(impl_) = item.kind &&
+ // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
+ // them up regardless of where they're located.
+ impl_.of_trait.is_none()
+ {
+ self.add_to_current_mod(item, None, None);
+ }
+ return;
+ }
let name = renamed.unwrap_or(item.ident.name);
let tcx = self.cx.tcx;
@@ -564,4 +586,10 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
fn visit_lifetime(&mut self, _: &hir::Lifetime) {
// Unneeded.
}
+
+ fn visit_body(&mut self, b: &'tcx hir::Body<'tcx>) {
+ let prev = mem::replace(&mut self.inside_body, true);
+ walk_body(self, b);
+ self.inside_body = prev;
+ }
}
diff --git a/tests/rustdoc/nested-items-issue-111415.rs b/tests/rustdoc/nested-items-issue-111415.rs
new file mode 100644
index 00000000000..9b7688c332c
--- /dev/null
+++ b/tests/rustdoc/nested-items-issue-111415.rs
@@ -0,0 +1,36 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/111415>.
+// This test ensures that only impl blocks are documented in bodies.
+
+#![crate_name = "foo"]
+
+// @has 'foo/index.html'
+// Checking there are only three sections.
+// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 3
+// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Structs'
+// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Functions'
+// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Traits'
+// Checking that there are only three items.
+// @count - '//*[@id="main-content"]//*[@class="item-name"]' 3
+// @has - '//*[@id="main-content"]//a[@href="struct.Bar.html"]' 'Bar'
+// @has - '//*[@id="main-content"]//a[@href="fn.foo.html"]' 'foo'
+// @has - '//*[@id="main-content"]//a[@href="trait.Foo.html"]' 'Foo'
+
+// Now checking that the `foo` method is visible in `Bar` page.
+// @has 'foo/struct.Bar.html'
+// @has - '//*[@id="method.foo"]/*[@class="code-header"]' 'pub fn foo()'
+// @has - '//*[@id="method.bar"]/*[@class="code-header"]' 'fn bar()'
+pub struct Bar;
+
+pub trait Foo {
+ fn bar() {}
+}
+
+pub fn foo() {
+ pub mod inaccessible {}
+ pub fn inner() {}
+ pub const BAR: u32 = 0;
+ impl Bar {
+ pub fn foo() {}
+ }
+ impl Foo for Bar {}
+}