about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume.gomez@huawei.com>2022-07-15 18:10:52 +0200
committerGuillaume Gomez <guillaume.gomez@huawei.com>2022-07-16 13:39:38 +0200
commit3c55a26cb489abd4c8e8dc4835bad77ec80be493 (patch)
treeff0313fd7c451d2105e40f079685d2c6eea36f29
parent1a15c7147f90afaa64ae3ff27fcbd678e2e44a8e (diff)
downloadrust-3c55a26cb489abd4c8e8dc4835bad77ec80be493.tar.gz
rust-3c55a26cb489abd4c8e8dc4835bad77ec80be493.zip
Correctly handle usage of private items in public API for JSON output format
-rw-r--r--src/librustdoc/core.rs3
-rw-r--r--src/librustdoc/passes/strip_private.rs1
-rw-r--r--src/librustdoc/passes/stripper.rs22
3 files changed, 22 insertions, 4 deletions
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index a658e78bf60..0e9a9e0e506 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -81,6 +81,8 @@ pub(crate) struct DocContext<'tcx> {
     pub(crate) inlined: FxHashSet<ItemId>,
     /// Used by `calculate_doc_coverage`.
     pub(crate) output_format: OutputFormat,
+    /// Used by `strip_private`.
+    pub(crate) show_coverage: bool,
 }
 
 impl<'tcx> DocContext<'tcx> {
@@ -381,6 +383,7 @@ pub(crate) fn run_global_ctxt(
         inlined: FxHashSet::default(),
         output_format,
         render_options,
+        show_coverage,
     };
 
     // Small hack to force the Sized trait to be present.
diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs
index 6c94912bc53..9ba841a31cf 100644
--- a/src/librustdoc/passes/strip_private.rs
+++ b/src/librustdoc/passes/strip_private.rs
@@ -24,6 +24,7 @@ pub(crate) fn strip_private(mut krate: clean::Crate, cx: &mut DocContext<'_>) ->
             retained: &mut retained,
             access_levels: &cx.cache.access_levels,
             update_retained: true,
+            is_json_output: cx.output_format.is_json() && !cx.show_coverage,
         };
         krate = ImportStripper.fold_crate(stripper.fold_crate(krate));
     }
diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs
index 0fd124e6154..5f2f50e712b 100644
--- a/src/librustdoc/passes/stripper.rs
+++ b/src/librustdoc/passes/stripper.rs
@@ -3,7 +3,7 @@ use rustc_hir::def_id::DefId;
 use rustc_middle::middle::privacy::AccessLevels;
 use std::mem;
 
-use crate::clean::{self, Item, ItemIdSet};
+use crate::clean::{self, Item, ItemId, ItemIdSet};
 use crate::fold::{strip_item, DocFolder};
 use crate::formats::cache::Cache;
 
@@ -11,6 +11,21 @@ pub(crate) struct Stripper<'a> {
     pub(crate) retained: &'a mut ItemIdSet,
     pub(crate) access_levels: &'a AccessLevels<DefId>,
     pub(crate) update_retained: bool,
+    pub(crate) is_json_output: bool,
+}
+
+impl<'a> Stripper<'a> {
+    // We need to handle this differently for the JSON output because some non exported items could
+    // be used in public API. And so, we need these items as well. `is_exported` only checks if they
+    // are in the public API, which is not enough.
+    #[inline]
+    fn is_item_reachable(&self, item_id: ItemId) -> bool {
+        if self.is_json_output {
+            self.access_levels.is_reachable(item_id.expect_def_id())
+        } else {
+            self.access_levels.is_exported(item_id.expect_def_id())
+        }
+    }
 }
 
 impl<'a> DocFolder for Stripper<'a> {
@@ -45,9 +60,8 @@ impl<'a> DocFolder for Stripper<'a> {
             | clean::TraitAliasItem(..)
             | clean::MacroItem(..)
             | clean::ForeignTypeItem => {
-                if i.item_id.is_local()
-                    && !self.access_levels.is_exported(i.item_id.expect_def_id())
-                {
+                let item_id = i.item_id;
+                if item_id.is_local() && !self.is_item_reachable(item_id) {
                     debug!("Stripper: stripping {:?} {:?}", i.type_(), i.name);
                     return None;
                 }