Skip to content
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

[rustdoc-json] JSON no longer inlines #93518

Closed
Closed
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
5 changes: 3 additions & 2 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2023,8 +2023,9 @@ fn clean_use_statement(
// forcefully don't inline if this is not public or if the
// #[doc(no_inline)] attribute is present.
// Don't inline doc(hidden) imports so they can be stripped at a later stage.
let mut denied = !(visibility.is_public()
|| (cx.render_options.document_private && is_visible_from_parent_mod))
let mut denied = cx.output_format.is_json()
|| !(visibility.is_public()
|| (cx.render_options.document_private && is_visible_from_parent_mod))
|| pub_underscore
|| attrs.iter().any(|a| {
a.has_name(sym::doc)
Expand Down
19 changes: 16 additions & 3 deletions src/librustdoc/json/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,15 @@ impl JsonRenderer<'_> {
let span = item.span(self.tcx);
let clean::Item { name, attrs: _, kind: _, visibility, def_id, cfg: _ } = item;
let inner = match *item.kind {
clean::StrippedItem(_) => return None,
clean::StrippedItem(ref inner) => {
match &**inner {
// We document non-empty stripped modules as a special StrippedModule type, 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),
_ => return None,
}
}
_ => from_clean_item(item, self.tcx),
};
Some(Item {
Expand Down Expand Up @@ -226,8 +234,13 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
bounds: g.into_iter().map(|x| x.into_tcx(tcx)).collect(),
default: t.map(|x| x.into_tcx(tcx)),
},
// `convert_item` early returns `None` for striped items
StrippedItem(_) => unreachable!(),
StrippedItem(inner) => {
match *inner {
ModuleItem(m) => ItemEnum::StrippedModule { items: ids(m.items) },
// `convert_item` early returns `None` for stripped items we're not including
_ => unreachable!(),
}
}
KeywordItem(_) => {
panic!("{:?} is not supported for JSON output", item)
}
Expand Down
10 changes: 9 additions & 1 deletion src/librustdoc/json/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use rustc_session::Session;
use rustdoc_json_types as types;

use crate::clean::types::{ExternalCrate, ExternalLocation};
use crate::clean::ItemKind;
use crate::config::RenderOptions;
use crate::docfs::PathError;
use crate::error::Error;
Expand Down Expand Up @@ -172,7 +173,14 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
/// the hashmap because certain items (traits and types) need to have their mappings for trait
/// implementations filled out before they're inserted.
fn item(&mut self, item: clean::Item) -> Result<(), Error> {
// Flatten items that recursively store other items
trace!("rendering {} {:?}", item.type_(), item.name);

// Flatten items that recursively store other items. We include orphaned items from
// stripped modules and etc that are otherwise reachable.
if let ItemKind::StrippedItem(inner) = &*item.kind {
inner.inner_items().for_each(|i| self.item(i.clone()).unwrap());
}

item.kind.inner_items().for_each(|i| self.item(i.clone()).unwrap());

let id = item.def_id;
Expand Down
4 changes: 4 additions & 0 deletions src/librustdoc/visit_ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
) -> bool {
debug!("maybe_inline_local res: {:?}", res);

if self.cx.output_format.is_json() {
return false;
}

let tcx = self.cx.tcx;
let res_did = if let Some(did) = res.opt_def_id() {
did
Expand Down
5 changes: 4 additions & 1 deletion src/rustdoc-json-types/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::path::PathBuf;
use serde::{Deserialize, Serialize};

/// rustdoc format-version.
pub const FORMAT_VERSION: u32 = 10;
pub const FORMAT_VERSION: u32 = 11;

/// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
/// about the language items in the local crate, as well as info about external items to allow
Expand Down Expand Up @@ -192,6 +192,9 @@ pub enum ItemKind {
#[serde(tag = "kind", content = "inner", rename_all = "snake_case")]
pub enum ItemEnum {
Module(Module),
StrippedModule {
Copy link
Member

@Enselic Enselic Feb 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For symmetry with most other enum variants, most notably Module(Module), this should be StrippedModule(StrippedModule).

Another option that I find even more attractive since it removes the need for more types and enum variants is to simply add is_stripped to struct Module, so it becomes:

pub struct Module {
    pub is_crate: bool,
    pub is_stripped: bool,
    pub items: Vec<Id>,
}

That would be even more symmetric with existing code, since there is no CrateModule (which would be an alternative to having the current is_crate field in Module).

items: Vec<Id>,
},
ExternCrate {
name: String,
rename: Option<String>,
Expand Down
1 change: 1 addition & 0 deletions src/test/rustdoc-json/reexport/auxiliary/pub-struct.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub struct Foo;
6 changes: 3 additions & 3 deletions src/test/rustdoc-json/reexport/glob_extern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
#![no_core]
#![feature(no_core)]

// @!has glob_extern.json "$.index[*][?(@.name=='mod1')]"
// @is glob_extern.json "$.index[*][?(@.name=='mod1')].kind" \"stripped_module\"
mod mod1 {
extern "C" {
// @set public_fn_id = - "$.index[*][?(@.name=='public_fn')].id"
// @has - "$.index[*][?(@.name=='public_fn')]"
pub fn public_fn();
// @!has - "$.index[*][?(@.name=='private_fn')]"
fn private_fn();
}
}

// @has - "$.index[*][?(@.name=='glob_extern')].inner.items[*]" $public_fn_id
// @is - "$.index[*][?(@.kind=='import')].inner.glob" true
pub use mod1::*;
12 changes: 8 additions & 4 deletions src/test/rustdoc-json/reexport/glob_private.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@
#![no_core]
#![feature(no_core)]

// @!has glob_private.json "$.index[*][?(@.name=='mod1')]"
// @is glob_private.json "$.index[*][?(@.name=='mod1')].kind" \"stripped_module\"
mod mod1 {
// @!has - "$.index[*][?(@.name=='mod2')]"
// @is - "$.index[*][?(@.name=='mod2')].kind" \"stripped_module\"
mod mod2 {
// @set m2pub_id = - "$.index[*][?(@.name=='Mod2Public')].id"
pub struct Mod2Public;

// @!has - "$.index[*][?(@.name=='Mod2Private')]"
struct Mod2Private;
}

// @has - "$.index[*][?(@.kind=='import' && @.inner.name=='mod2')]"
pub use self::mod2::*;

// @set m1pub_id = - "$.index[*][?(@.name=='Mod1Public')].id"
Expand All @@ -21,7 +23,9 @@ mod mod1 {
// @!has - "$.index[*][?(@.name=='Mod1Private')]"
struct Mod1Private;
}

// @has - "$.index[*][?(@.kind=='import' && @.inner.name=='mod1')]"
pub use mod1::*;

// @has - "$.index[*][?(@.name=='glob_private')].inner.items[*]" $m2pub_id
// @has - "$.index[*][?(@.name=='glob_private')].inner.items[*]" $m1pub_id
// @has - "$.index[*][?(@.name=='mod2')].inner.items[*]" $m2pub_id
// @has - "$.index[*][?(@.name=='mod1')].inner.items[*]" $m1pub_id
7 changes: 4 additions & 3 deletions src/test/rustdoc-json/reexport/in_root_and_mod.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
#![feature(no_core)]
#![no_core]

// @is in_root_and_mod.json "$.index[*][?(@.name=='foo')].kind" \"stripped_module\"
mod foo {
// @set foo_id = in_root_and_mod.json "$.index[*][?(@.name=='Foo')].id"
// @has - "$.index[*][?(@.name=='Foo')]"
pub struct Foo;
}

// @has - "$.index[*][?(@.name=='in_root_and_mod')].inner.items[*]" $foo_id
// @has - "$.index[*][?(@.kind=='import' && @.inner.source=='foo::Foo')]"
pub use foo::Foo;

pub mod bar {
// @has - "$.index[*][?(@.name=='bar')].inner.items[*]" $foo_id
// @has - "$.index[*][?(@.kind=='import' && @.inner.source=='crate::foo::Foo')]"
pub use crate::foo::Foo;
}
18 changes: 18 additions & 0 deletions src/test/rustdoc-json/reexport/private_twice_one_inline.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// aux-build:pub-struct.rs

// Test for the ICE in rust/83057
// Am external type re-exported with different attributes shouldn't cause an error

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

extern crate pub_struct as foo;

#[doc(inline)]
pub use foo::Foo;

pub mod bar {
pub use foo::Foo;
}

// @count private_twice_one_inline.json "$.index[*][?(@.kind=='import')]" 2
16 changes: 16 additions & 0 deletions src/test/rustdoc-json/reexport/private_two_names.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Test for the ICE in rust/83720
// A pub-in-private type re-exported under two different names shouldn't cause an error

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

// @is private_two_names.json "$.index[*][?(@.name=='style')].kind" \"stripped_module\"
mod style {
// @has - "$.index[*](?(@.name=='Color'))"
pub struct Color;
}

// @has - "$.index[*][?(@.kind=='import' && @.inner.name=='Color')]"
pub use style::Color;
// @has - "$.index[*][?(@.kind=='import' && @.inner.name=='Colour')]"
pub use style::Color as Colour;
9 changes: 4 additions & 5 deletions src/test/rustdoc-json/reexport/rename_private.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

#![no_core]
#![feature(no_core)]
// @!has rename_private.json "$.index[*][?(@.name=='inner')]"

// @is rename_private.json "$.index[*][?(@.name=='inner')].kind" \"stripped_module\"
mod inner {
// @!has - "$.index[*][?(@.name=='Public')]"
// @has - "$.index[*][?(@.name=='Public')]"
pub struct Public;
}

// @set newname_id = - "$.index[*][?(@.name=='NewName')].id"
// @is - "$.index[*][?(@.name=='NewName')].kind" \"struct\"
// @has - "$.index[*][?(@.name=='rename_private')].inner.items[*]" $newname_id
// @is - "$.index[*][?(@.kind=='import')].inner.name" \"NewName\"
pub use inner::Public as NewName;
6 changes: 4 additions & 2 deletions src/test/rustdoc-json/reexport/simple_private.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
#![no_core]
#![feature(no_core)]

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

// @has - "$.index[*][?(@.name=='simple_private')].inner.items[*]" $pub_id
// @is - "$.index[*][?(@.kind=='import')].inner.name" \"Public\"
pub use inner::Public;

// @has - "$.index[*][?(@.name=='inner')].inner.items[*]" $pub_id
21 changes: 21 additions & 0 deletions src/test/rustdoc-json/stripped_modules.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#![no_core]
#![feature(no_core)]

// @!has stripped_modules.json "$.index[*][?(@.name=='no_pub_inner')]"
mod no_pub_inner {
fn priv_inner() {}
}

// @!has - "$.index[*][?(@.name=='pub_inner_unreachable')]"
mod pub_inner_unreachable {
// @!has - "$.index[*][?(@.name=='pub_inner_1')]"
pub fn pub_inner_1() {}
}

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

pub use pub_inner_reachable::pub_inner_2;