Skip to content

Commit e100df9

Browse files
Rollup merge of #112836 - GuillaumeGomez:rustdoc-invalid-file-creation, r=notriddle
[rustdoc] partially fix invalid files creation Part of #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

9 files changed

+138
-22
lines changed

src/librustdoc/clean/types.rs

+13-9
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

+5
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

+34-7
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

+5-2
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.
+23
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;
+18
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

+4-4
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 {
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

+2
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)