Skip to content

Rustdoc-Json: Retain Stripped Modules when they are imported, not when they have items #101106

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/etc/check_missing_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,9 @@ def check_type(ty):
check_generic_bound(bound)
if item["inner"]["default"]:
check_type(item["inner"]["default"])
elif item["kind"] == "import":
if item["inner"]["id"]:
inner_id = item["inner"]["id"]
assert valid_id(inner_id)
if inner_id in crate["index"] and inner_id not in visited:
work_list.add(inner_id)
8 changes: 6 additions & 2 deletions src/librustdoc/json/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,14 @@ impl JsonRenderer<'_> {
clean::KeywordItem => return None,
clean::StrippedItem(ref inner) => {
match &**inner {
// We document non-empty stripped modules as with `Module::is_stripped` set to
// We document stripped modules as with `Module::is_stripped` set to
// `true`, to prevent contained items from being orphaned for downstream users,
// as JSON does no inlining.
clean::ModuleItem(m) if !m.items.is_empty() => from_clean_item(item, self.tcx),
clean::ModuleItem(_)
if self.imported_items.contains(&item_id.expect_def_id()) =>
{
from_clean_item(item, self.tcx)
}
_ => return None,
}
}
Expand Down
38 changes: 38 additions & 0 deletions src/librustdoc/json/import_finder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::DefId;

use crate::{
clean::{self, Import, ImportSource, Item},
fold::DocFolder,
};

/// Get the id's of all items that are `pub use`d in the crate.
///
/// We need this to know if a stripped module is `pub use mod::*`, to decide
/// if it needs to be kept in the index, despite being stripped.
///
/// See [#100973](https://github.com/rust-lang/rust/issues/100973) and
/// [#101103](https://github.com/rust-lang/rust/issues/101103) for times when
/// this information is needed.
pub(crate) fn get_imports(krate: clean::Crate) -> (clean::Crate, FxHashSet<DefId>) {
let mut finder = ImportFinder { imported: FxHashSet::default() };
let krate = finder.fold_crate(krate);
(krate, finder.imported)
}

struct ImportFinder {
imported: FxHashSet<DefId>,
}

impl DocFolder for ImportFinder {
fn fold_item(&mut self, i: Item) -> Option<Item> {
match *i.kind {
clean::ImportItem(Import { source: ImportSource { did: Some(did), .. }, .. }) => {
self.imported.insert(did);
Some(i)
}

_ => Some(self.fold_item_recur(i)),
}
}
}
8 changes: 7 additions & 1 deletion src/librustdoc/json/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
//! docs for usage and details.

mod conversions;
mod import_finder;

use std::cell::RefCell;
use std::fs::{create_dir_all, File};
use std::io::{BufWriter, Write};
use std::path::PathBuf;
use std::rc::Rc;

use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def_id::DefId;
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
Expand All @@ -39,6 +40,7 @@ pub(crate) struct JsonRenderer<'tcx> {
/// The directory where the blob will be written to.
out_path: PathBuf,
cache: Rc<Cache>,
imported_items: FxHashSet<DefId>,
}

impl<'tcx> JsonRenderer<'tcx> {
Expand Down Expand Up @@ -157,12 +159,16 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
tcx: TyCtxt<'tcx>,
) -> Result<(Self, clean::Crate), Error> {
debug!("Initializing json renderer");

let (krate, imported_items) = import_finder::get_imports(krate);

Ok((
JsonRenderer {
tcx,
index: Rc::new(RefCell::new(FxHashMap::default())),
out_path: options.output,
cache: Rc::new(cache),
imported_items,
},
krate,
))
Expand Down
28 changes: 28 additions & 0 deletions src/test/rustdoc-json/reexport/glob_collision.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Regression test for https://github.com/rust-lang/rust/issues/100973

#![feature(no_core)]
#![no_core]

// @set m1 = "$.index[*][?(@.name == 'm1' && @.kind == 'module')].id"
// @is "$.index[*][?(@.name == 'm1' && @.kind == 'module')].inner.items" []
// @is "$.index[*][?(@.name == 'm1' && @.kind == 'module')].inner.is_stripped" true
mod m1 {
pub fn f() {}
}
// @set m2 = "$.index[*][?(@.name == 'm2' && @.kind == 'module')].id"
// @is "$.index[*][?(@.name == 'm2' && @.kind == 'module')].inner.items" []
// @is "$.index[*][?(@.name == 'm2' && @.kind == 'module')].inner.is_stripped" true
mod m2 {
pub fn f(_: u8) {}
}

// @set m1_use = "$.index[*][?(@.inner.name=='m1')].id"
// @is "$.index[*][?(@.inner.name=='m1')].inner.id" $m1
// @is "$.index[*][?(@.inner.name=='m1')].inner.glob" true
pub use m1::*;
// @set m2_use = "$.index[*][?(@.inner.name=='m2')].id"
// @is "$.index[*][?(@.inner.name=='m2')].inner.id" $m2
// @is "$.index[*][?(@.inner.name=='m2')].inner.glob" true
pub use m2::*;

// @ismany "$.index[*][?(@.inner.is_crate==true)].inner.items[*]" $m1_use $m2_use
8 changes: 8 additions & 0 deletions src/test/rustdoc-json/reexport/glob_empty_mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Regression test for https://github.com/rust-lang/rust/issues/100973

// @is "$.index[*][?(@.name=='m1' && @.kind == 'module')].inner.is_stripped" true
// @set m1 = "$.index[*][?(@.name=='m1')].id"
mod m1 {}

// @is "$.index[*][?(@.inner.name=='m1' && @.kind=='import')].inner.id" $m1
pub use m1::*;
3 changes: 1 addition & 2 deletions src/test/rustdoc-json/reexport/in_root_and_mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#![feature(no_core)]
#![no_core]

// @is "$.index[*][?(@.name=='foo')].kind" \"module\"
// @is "$.index[*][?(@.name=='foo')].inner.is_stripped" "true"
// @!has "$.index[*][?(@.name=='foo')]"
mod foo {
// @has "$.index[*][?(@.name=='Foo')]"
pub struct Foo;
Expand Down
14 changes: 14 additions & 0 deletions src/test/rustdoc-json/reexport/mod_not_included.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Regression test for https://github.com/rust-lang/rust/issues/101103

#![feature(no_core)]
#![no_core]

mod m1 {
pub fn x() {}
}

pub use m1::x;

// @has "$.index[*][?(@.name=='x' && @.kind=='function')]"
// @has "$.index[*][?(@.kind=='import' && @.inner.name=='x')].inner.source" '"m1::x"'
// @!has "$.index[*][?(@.name=='m1')]"
3 changes: 1 addition & 2 deletions src/test/rustdoc-json/reexport/private_two_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
#![no_core]
#![feature(no_core)]

// @is "$.index[*][?(@.name=='style')].kind" \"module\"
// @is "$.index[*][?(@.name=='style')].inner.is_stripped" "true"
// @!has "$.index[*][?(@.name=='style')]"
mod style {
// @set color_struct_id = "$.index[*][?(@.kind=='struct' && @.name=='Color')].id"
pub struct Color;
Expand Down
3 changes: 1 addition & 2 deletions src/test/rustdoc-json/reexport/rename_private.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
#![no_core]
#![feature(no_core)]

// @is "$.index[*][?(@.name=='inner')].kind" \"module\"
// @is "$.index[*][?(@.name=='inner')].inner.is_stripped" "true"
// @!has "$.index[*][?(@.kind=='inner')]"
mod inner {
// @has "$.index[*][?(@.name=='Public')]"
pub struct Public;
Expand Down
5 changes: 2 additions & 3 deletions src/test/rustdoc-json/reexport/simple_private.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@
#![no_core]
#![feature(no_core)]

// @is "$.index[*][?(@.name=='inner')].kind" \"module\"
// @is "$.index[*][?(@.name=='inner')].inner.is_stripped" "true"
// @!has "$.index[*][?(@.name=='inner')]"
mod inner {
// @set pub_id = "$.index[*][?(@.name=='Public')].id"
pub struct Public;
}

// @is "$.index[*][?(@.kind=='import')].inner.name" \"Public\"
// @is "$.index[*][?(@.kind=='import')].inner.id" $pub_id
// @set use_id = "$.index[*][?(@.kind=='import')].id"
pub use inner::Public;

// @ismany "$.index[*][?(@.name=='inner')].inner.items[*]" $pub_id
// @ismany "$.index[*][?(@.name=='simple_private')].inner.items[*]" $use_id
2 changes: 1 addition & 1 deletion src/test/rustdoc-json/stripped_modules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ mod pub_inner_unreachable {
pub fn pub_inner_1() {}
}

// @has "$.index[*][?(@.name=='pub_inner_reachable')]"
// @!has "$.index[*][?(@.name=='pub_inner_reachable')]"
mod pub_inner_reachable {
// @has "$.index[*][?(@.name=='pub_inner_2')]"
pub fn pub_inner_2() {}
Expand Down