Skip to content

Fix --document-private-items not documenting private re-exports of hi…#159146

Open
mansiverma897993 wants to merge 1 commit into
rust-lang:mainfrom
mansiverma897993:fix-rustdoc-private-reexports-159109
Open

Fix --document-private-items not documenting private re-exports of hi…#159146
mansiverma897993 wants to merge 1 commit into
rust-lang:mainfrom
mansiverma897993:fix-rustdoc-private-reexports-159109

Conversation

@mansiverma897993

@mansiverma897993 mansiverma897993 commented Jul 11, 2026

Copy link
Copy Markdown

Fixes #159109

Under --document-private-items, rustdoc is expected to document private items and private re-exports. However, when a private re-export (e.g. pub(crate) use) with #[doc(inline)] points to a private/hidden item, it was not being documented.

Root Cause

  1. In src/librustdoc/visit_ast.rs, the AST is traversed to find items to document. RustdocVisitor determines if an item/module is public (is_pub and inside_public_path) based on whether its visibility is public.
  2. Since private re-exports are not public, is_pub was computed as false, and local inlining (maybe_inline_local) was skipped.
  3. Because the item was not locally inlined, it remained an ImportItem in the clean representation and was subsequently stripped by the strip-hidden pass because the target item was marked #[doc(hidden)].

Fix

  1. Updated RustdocVisitor in src/librustdoc/visit_ast.rs to treat private items, parent modules, and foreign items as public (making them eligible for local inlining) when document_private is active.
  2. Updated clean_extern_crate in src/librustdoc/clean/mod.rs to allow inlining of private extern crate statements if document_private is active.
  3. Added a regression test case tests/rustdoc-html/document-private-items-reexports.rs that validates private re-exports are correctly documented.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. T-rustdoc-frontend Relevant to the rustdoc-frontend team, which will review and decide on the web UI/UX output. labels Jul 11, 2026
@rustbot

rustbot commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the pull request, and welcome! The Rust Project is excited to review your changes, and you should hear from @GuillaumeGomez (or someone else) some time within the next two weeks.

Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (S-waiting-on-review and S-waiting-on-author) stays updated, invoking these commands when appropriate:

  • @rustbot author: the review is finished, PR author should check the comments and take action accordingly
  • @rustbot review: the author is ready for a review, this PR will be queued again in the reviewer's queue
Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: rustdoc
  • rustdoc expanded to 8 candidates
  • Random selection from GuillaumeGomez, lolbinarycat, notriddle

@rust-log-analyzer

Copy link
Copy Markdown
Collaborator

The job tidy failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
[TIMING:end] tool::ToolBuild { build_compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu, tool: "tidy", path: "src/tools/tidy", mode: ToolBootstrap, source_type: InTree, extra_features: [], allow_features: "", cargo_args: [], artifact_kind: Binary } -- 10.430
[TIMING:end] tool::Tidy { compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu } -- 0.000
fmt check
Diff in /checkout/src/librustdoc/passes/strip_private.rs:29:
             is_json_output,
             tcx: cx.tcx,
         };
-        krate =
-            ImportStripper {
-                tcx: cx.tcx,
-                document_private: cx.document_private(),
-                is_json_output,
-                document_hidden: cx.document_hidden(),
-            }
-            .fold_crate(stripper.fold_crate(krate));
+        krate = ImportStripper {
+            tcx: cx.tcx,
+            document_private: cx.document_private(),
+            is_json_output,
+            document_hidden: cx.document_hidden(),
+        }
+        .fold_crate(stripper.fold_crate(krate));
     }
 
     // strip all impls referencing private items
Diff in /checkout/src/librustdoc/visit_ast.rs:206:
         debug!("Going through module {m:?}");
         // Keep track of if there were any private modules in the path.
         let orig_inside_public_path = self.inside_public_path;
-        self.inside_public_path &= self.cx.tcx.local_visibility(def_id).is_public()
-            || self.cx.document_private();
+        self.inside_public_path &=
+            self.cx.tcx.local_visibility(def_id).is_public() || self.cx.document_private();
 
         // Reimplementation of `walk_mod` because we need to do it in two passes (explanations in
         // the second loop):
Diff in /checkout/src/librustdoc/clean/mod.rs:1681:
                         if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = res {
                             continue;
                         }
-                        if (cx.document_hidden() ||
-                            !cx.tcx.is_doc_hidden(use_def_id)) &&
-                            (cx.tcx.local_visibility(local_use_def_id).is_public()
+                        if (cx.document_hidden() || !cx.tcx.is_doc_hidden(use_def_id))
+                            && (cx.tcx.local_visibility(local_use_def_id).is_public()
                                 || cx.document_private())
                         {
                             break 'reexps;
Diff in /checkout/src/librustdoc/clean/mod.rs:3193:
     // `pub(super)` or higher. If the current module is the top level
     // module, there isn't really a parent module, which makes the results
     // meaningless. In this case, we make sure the answer is `false`.
-    let is_visible_from_parent_mod =
-        visibility.is_accessible_from(parent_mod, cx.tcx)
-            && (!current_mod.is_top_level_module() || !import.vis_span.is_empty());
+    let is_visible_from_parent_mod = visibility.is_accessible_from(parent_mod, cx.tcx)
+        && (!current_mod.is_top_level_module() || !import.vis_span.is_empty());
 
     if pub_underscore && let Some((_, inline_span)) = inline_attr {
         struct_span_code_err!(
Diff in /checkout/src/librustdoc/clean/mod.rs:3224:
     // Also check whether imports were asked to be inlined, in case we're trying to re-export a
     // crate in Rust 2018+
     let path = clean_path(path, cx);
-    let should_be_displayed = visibility.is_public()
-        || (cx.document_private() && !import.vis_span.is_empty());
+    let should_be_displayed =
+        visibility.is_public() || (cx.document_private() && !import.vis_span.is_empty());
 
     let inner = if kind == hir::UseKind::Glob {
         if !denied {
fmt: checked 7016 files
Bootstrap failed while executing `test src/tools/tidy tidyselftest --extra-checks=py,cpp,js,spellcheck`
Currently active steps:
test::Tidy {  } at src/bootstrap/src/core/build_steps/test.rs:1566
Build completed unsuccessfully in 0:00:46

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. T-rustdoc-frontend Relevant to the rustdoc-frontend team, which will review and decide on the web UI/UX output.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

--document-private-items does not document private reexports

4 participants