Skip to content

Commit 63a291f

Browse files
committed
Fix rustdoc infinitely recursing when an external crate reexports itself
Previously, rustdoc's LibEmbargoVisitor unconditionally visited the child modules of an external crate. If a module re-exported its parent via 'pub use super::*', rustdoc would re-walk the parent, leading to infinite recursion. This commit makes LibEmbargoVisitor store already visited modules in an FxHashSet, ensuring that each module is only walked once. Fixes rust-lang#40936
1 parent 53f4bc3 commit 63a291f

File tree

3 files changed

+39
-0
lines changed

3 files changed

+39
-0
lines changed

src/librustdoc/visit_lib.rs

+8
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use rustc::middle::privacy::{AccessLevels, AccessLevel};
1313
use rustc::hir::def::Def;
1414
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
1515
use rustc::ty::Visibility;
16+
use rustc::util::nodemap::FxHashSet;
1617

1718
use std::cell::RefMut;
1819

@@ -29,6 +30,8 @@ pub struct LibEmbargoVisitor<'a, 'b: 'a, 'tcx: 'b> {
2930
access_levels: RefMut<'a, AccessLevels<DefId>>,
3031
// Previous accessibility level, None means unreachable
3132
prev_level: Option<AccessLevel>,
33+
// Keeps track of already visited modules, in case a module re-exports its parent
34+
visited_mods: FxHashSet<DefId>,
3235
}
3336

3437
impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> {
@@ -38,6 +41,7 @@ impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> {
3841
cstore: &*cx.sess().cstore,
3942
access_levels: cx.access_levels.borrow_mut(),
4043
prev_level: Some(AccessLevel::Public),
44+
visited_mods: FxHashSet()
4145
}
4246
}
4347

@@ -62,6 +66,10 @@ impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> {
6266
}
6367

6468
pub fn visit_mod(&mut self, def_id: DefId) {
69+
if !self.visited_mods.insert(def_id) {
70+
return;
71+
}
72+
6573
for item in self.cstore.item_children(def_id) {
6674
self.visit_item(item.def);
6775
}
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
pub mod outermod {
12+
pub mod innermod {
13+
pub use super::*;
14+
}
15+
}

src/test/rustdoc/issue-40936.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:issue-40936.rs
12+
// build-aux-docs
13+
14+
#![crate_name = "foo"]
15+
16+
extern crate issue_40936;

0 commit comments

Comments
 (0)