Skip to content

Commit e100df9

Browse files
Rollup merge of rust-lang#112836 - GuillaumeGomez:rustdoc-invalid-file-creation, r=notriddle
[rustdoc] partially fix invalid files creation Part of rust-lang#111249. It only removes generation for modules which shouldn't exist. For files, we need the compiler to keep re-export information alive for external items so we can actually have the right path to their ___location as it's currently not generating them correctly. In case the item is inlined, it shouldn't (and neither should its children) get a file generated. r? ```@notriddle```
2 parents 476798d + 3ad595a commit e100df9

File tree

9 files changed

+138
-22
lines changed

9 files changed

+138
-22
lines changed

src/librustdoc/clean/types.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -358,15 +358,15 @@ fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
358358

359359
impl Item {
360360
pub(crate) fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<Stability> {
361-
self.item_id.as_def_id().and_then(|did| tcx.lookup_stability(did))
361+
self.def_id().and_then(|did| tcx.lookup_stability(did))
362362
}
363363

364364
pub(crate) fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<ConstStability> {
365-
self.item_id.as_def_id().and_then(|did| tcx.lookup_const_stability(did))
365+
self.def_id().and_then(|did| tcx.lookup_const_stability(did))
366366
}
367367

368368
pub(crate) fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
369-
self.item_id.as_def_id().and_then(|did| tcx.lookup_deprecation(did))
369+
self.def_id().and_then(|did| tcx.lookup_deprecation(did))
370370
}
371371

372372
pub(crate) fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
@@ -391,7 +391,7 @@ impl Item {
391391
panic!("blanket impl item has non-blanket ID")
392392
}
393393
}
394-
_ => self.item_id.as_def_id().map(|did| rustc_span(did, tcx)),
394+
_ => self.def_id().map(|did| rustc_span(did, tcx)),
395395
}
396396
}
397397

@@ -501,7 +501,7 @@ impl Item {
501501
}
502502

503503
pub(crate) fn is_crate(&self) -> bool {
504-
self.is_mod() && self.item_id.as_def_id().map_or(false, |did| did.is_crate_root())
504+
self.is_mod() && self.def_id().map_or(false, |did| did.is_crate_root())
505505
}
506506
pub(crate) fn is_mod(&self) -> bool {
507507
self.type_() == ItemType::Module
@@ -638,11 +638,11 @@ impl Item {
638638
}
639639
let header = match *self.kind {
640640
ItemKind::ForeignFunctionItem(_) => {
641-
let def_id = self.item_id.as_def_id().unwrap();
641+
let def_id = self.def_id().unwrap();
642642
let abi = tcx.fn_sig(def_id).skip_binder().abi();
643643
hir::FnHeader {
644644
unsafety: if abi == Abi::RustIntrinsic {
645-
intrinsic_operation_unsafety(tcx, self.item_id.as_def_id().unwrap())
645+
intrinsic_operation_unsafety(tcx, self.def_id().unwrap())
646646
} else {
647647
hir::Unsafety::Unsafe
648648
},
@@ -659,7 +659,7 @@ impl Item {
659659
}
660660
}
661661
ItemKind::FunctionItem(_) | ItemKind::MethodItem(_, _) | ItemKind::TyMethodItem(_) => {
662-
let def_id = self.item_id.as_def_id().unwrap();
662+
let def_id = self.def_id().unwrap();
663663
build_fn_header(def_id, tcx, tcx.asyncness(def_id))
664664
}
665665
_ => return None,
@@ -738,7 +738,7 @@ impl Item {
738738
}
739739
})
740740
.collect();
741-
if let Some(def_id) = self.item_id.as_def_id() &&
741+
if let Some(def_id) = self.def_id() &&
742742
!def_id.is_local() &&
743743
// This check is needed because `adt_def` will panic if not a compatible type otherwise...
744744
matches!(self.type_(), ItemType::Struct | ItemType::Enum | ItemType::Union)
@@ -787,6 +787,10 @@ impl Item {
787787
pub fn is_doc_hidden(&self) -> bool {
788788
self.attrs.is_doc_hidden()
789789
}
790+
791+
pub fn def_id(&self) -> Option<DefId> {
792+
self.item_id.as_def_id()
793+
}
790794
}
791795

792796
#[derive(Clone, Debug)]

src/librustdoc/formats/cache.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,11 @@ pub(crate) struct Cache {
121121
pub(crate) intra_doc_links: FxHashMap<ItemId, FxIndexSet<clean::ItemLink>>,
122122
/// Cfg that have been hidden via #![doc(cfg_hide(...))]
123123
pub(crate) hidden_cfg: FxHashSet<clean::cfg::Cfg>,
124+
125+
/// Contains the list of `DefId`s which have been inlined. It is used when generating files
126+
/// to check if a stripped item should get its file generated or not: if it's inside a
127+
/// `#[doc(hidden)]` item or a private one and not inlined, it shouldn't get a file.
128+
pub(crate) inlined_items: DefIdSet,
124129
}
125130

126131
/// This struct is used to wrap the `cache` and `tcx` in order to run `DocFolder`.

src/librustdoc/html/render/context.rs

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ pub(crate) struct Context<'tcx> {
7373
pub(crate) include_sources: bool,
7474
/// Collection of all types with notable traits referenced in the current module.
7575
pub(crate) types_with_notable_traits: FxHashSet<clean::Type>,
76+
/// Field used during rendering, to know if we're inside an inlined item.
77+
pub(crate) is_inside_inlined_module: bool,
7678
}
7779

7880
// `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
@@ -171,6 +173,19 @@ impl<'tcx> Context<'tcx> {
171173
}
172174

173175
fn render_item(&mut self, it: &clean::Item, is_module: bool) -> String {
176+
let mut render_redirect_pages = self.render_redirect_pages;
177+
// If the item is stripped but inlined, links won't point to the item so no need to generate
178+
// a file for it.
179+
if it.is_stripped() &&
180+
let Some(def_id) = it.def_id() &&
181+
def_id.is_local()
182+
{
183+
if self.is_inside_inlined_module || self.shared.cache.inlined_items.contains(&def_id) {
184+
// For now we're forced to generate a redirect page for stripped items until
185+
// `record_extern_fqn` correctly points to external items.
186+
render_redirect_pages = true;
187+
}
188+
}
174189
let mut title = String::new();
175190
if !is_module {
176191
title.push_str(it.name.unwrap().as_str());
@@ -205,7 +220,7 @@ impl<'tcx> Context<'tcx> {
205220
tyname.as_str()
206221
};
207222

208-
if !self.render_redirect_pages {
223+
if !render_redirect_pages {
209224
let clone_shared = Rc::clone(&self.shared);
210225
let page = layout::Page {
211226
css_class: tyname_s,
@@ -545,6 +560,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
545560
shared: Rc::new(scx),
546561
include_sources,
547562
types_with_notable_traits: FxHashSet::default(),
563+
is_inside_inlined_module: false,
548564
};
549565

550566
if emit_crate {
@@ -574,6 +590,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
574590
shared: Rc::clone(&self.shared),
575591
include_sources: self.include_sources,
576592
types_with_notable_traits: FxHashSet::default(),
593+
is_inside_inlined_module: self.is_inside_inlined_module,
577594
}
578595
}
579596

@@ -768,12 +785,22 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
768785

769786
info!("Recursing into {}", self.dst.display());
770787

771-
let buf = self.render_item(item, true);
772-
// buf will be empty if the module is stripped and there is no redirect for it
773-
if !buf.is_empty() {
774-
self.shared.ensure_dir(&self.dst)?;
775-
let joint_dst = self.dst.join("index.html");
776-
self.shared.fs.write(joint_dst, buf)?;
788+
if !item.is_stripped() {
789+
let buf = self.render_item(item, true);
790+
// buf will be empty if the module is stripped and there is no redirect for it
791+
if !buf.is_empty() {
792+
self.shared.ensure_dir(&self.dst)?;
793+
let joint_dst = self.dst.join("index.html");
794+
self.shared.fs.write(joint_dst, buf)?;
795+
}
796+
}
797+
if !self.is_inside_inlined_module {
798+
if let Some(def_id) = item.def_id() && self.cache().inlined_items.contains(&def_id) {
799+
self.is_inside_inlined_module = true;
800+
}
801+
} else if item.is_doc_hidden() {
802+
// We're not inside an inlined module anymore since this one cannot be re-exported.
803+
self.is_inside_inlined_module = false;
777804
}
778805

779806
// Render sidebar-items.js used throughout this module.

src/librustdoc/visit_ast.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
313313
return false;
314314
}
315315

316-
let ret = match tcx.hir().get_by_def_id(res_did) {
316+
let inlined = match tcx.hir().get_by_def_id(res_did) {
317317
// Bang macros are handled a bit on their because of how they are handled by the
318318
// compiler. If they have `#[doc(hidden)]` and the re-export doesn't have
319319
// `#[doc(inline)]`, then we don't inline it.
@@ -344,7 +344,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
344344
_ => false,
345345
};
346346
self.view_item_stack.remove(&res_did);
347-
ret
347+
if inlined {
348+
self.cx.cache.inlined_items.insert(res_did.to_def_id());
349+
}
350+
inlined
348351
}
349352

350353
/// Returns `true` if the item is visible, meaning it's not `#[doc(hidden)]` or private.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#![crate_name="foo"]
2+
3+
// @!has "foo/struct.Foo.html"
4+
#[doc(hidden)]
5+
pub struct Foo;
6+
7+
// @!has "foo/struct.Bar.html"
8+
pub use crate::Foo as Bar;
9+
10+
// @!has "foo/struct.Baz.html"
11+
#[doc(hidden)]
12+
pub use crate::Foo as Baz;
13+
14+
// @!has "foo/foo/index.html"
15+
#[doc(hidden)]
16+
pub mod foo {}
17+
18+
// @!has "foo/bar/index.html"
19+
pub use crate::foo as bar;
20+
21+
// @!has "foo/baz/index.html"
22+
#[doc(hidden)]
23+
pub use crate::foo as baz;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#![crate_name="foo"]
2+
3+
// @!has "foo/priv/index.html"
4+
// @!has "foo/priv/struct.Foo.html"
5+
mod private {
6+
pub struct Foo;
7+
}
8+
9+
// @has "foo/struct.Bar.html"
10+
pub use crate::private::Foo as Bar;
11+
12+
// @!has "foo/foo/index.html"
13+
mod foo {
14+
pub mod subfoo {}
15+
}
16+
17+
// @has "foo/bar/index.html"
18+
pub use crate::foo::subfoo as bar;

tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
#![crate_name = "foo"]
44

55
// @!has 'foo/hidden/index.html'
6-
// FIXME: add missing `@` for the two next tests once issue is fixed!
7-
// To be done in <https://github.com/rust-lang/rust/issues/111249>.
8-
// !has 'foo/hidden/inner/index.html'
9-
// !has 'foo/hidden/inner/trait.Foo.html'
6+
// @!has 'foo/hidden/inner/index.html'
7+
// FIXME: Should be `@!has`: https://github.com/rust-lang/rust/issues/111249
8+
// @has 'foo/hidden/inner/trait.Foo.html'
9+
// @matchesraw - '<meta http-equiv="refresh" content="0;URL=../../../foo/visible/trait.Foo.html">'
1010
#[doc(hidden)]
1111
pub mod hidden {
1212
pub mod inner {
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#![crate_name = "foo"]
2+
#![feature(no_core)]
3+
#![no_core]
4+
5+
// The following five should not fail!
6+
// @!has 'foo/hidden/index.html'
7+
// @!has 'foo/hidden/inner/index.html'
8+
// FIXME: Should be `@!has`: https://github.com/rust-lang/rust/issues/111249
9+
// @has 'foo/hidden/inner/trait.Foo.html'
10+
// @matchesraw - '<meta http-equiv="refresh" content="0;URL=../../../foo/visible/trait.Foo.html">'
11+
// @!has 'foo/hidden/inner/inner_hidden/index.html'
12+
// @!has 'foo/hidden/inner/inner_hidden/trait.HiddenFoo.html'
13+
#[doc(hidden)]
14+
pub mod hidden {
15+
pub mod inner {
16+
pub trait Foo {}
17+
18+
#[doc(hidden)]
19+
pub mod inner_hidden {
20+
pub trait HiddenFoo {}
21+
}
22+
}
23+
}
24+
25+
// @has 'foo/visible/index.html'
26+
// @has 'foo/visible/trait.Foo.html'
27+
#[doc(inline)]
28+
pub use hidden::inner as visible;
29+
30+
// @has 'foo/struct.Bar.html'
31+
// @count - '//*[@id="impl-Foo-for-Bar"]' 1
32+
pub struct Bar;
33+
34+
impl visible::Foo for Bar {}

tests/rustdoc/redirect.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ pub trait Foo {}
1010
// @has - '//code' 'pub use reexp_stripped::Bar'
1111
// @has - '//code/a' 'Bar'
1212
// @has - '//a[@href="../reexp_stripped/hidden/struct.Bar.html"]' 'Bar'
13+
// FIXME: Should be `@!has`: https://github.com/rust-lang/rust/issues/111249
1314
// @has reexp_stripped/hidden/struct.Bar.html
15+
// @matchesraw - '<meta http-equiv="refresh" content="0;URL=../../reexp_stripped/struct.Bar.html">'
1416
// @has 'reexp_stripped/struct.Bar.html'
1517
// @has - '//a[@href="struct.Bar.html"]' 'Bar'
1618
#[doc(no_inline)]

0 commit comments

Comments
 (0)