about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAaron Hill <aa1ronham@gmail.com>2017-04-09 12:00:34 -0400
committerAaron Hill <aa1ronham@gmail.com>2017-04-09 12:12:05 -0400
commit63a291febac3ba2cb48787fed24388c2817ef4a2 (patch)
treeb363bb6ae1dd08b28f2d687932825a42651c225a /src
parent53f4bc311b5ff11a16185dd40dc116cf6b8cc162 (diff)
downloadrust-63a291febac3ba2cb48787fed24388c2817ef4a2.tar.gz
rust-63a291febac3ba2cb48787fed24388c2817ef4a2.zip
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 #40936
Diffstat (limited to 'src')
-rw-r--r--src/librustdoc/visit_lib.rs8
-rw-r--r--src/test/rustdoc/auxiliary/issue-40936.rs15
-rw-r--r--src/test/rustdoc/issue-40936.rs16
3 files changed, 39 insertions, 0 deletions
diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs
index 852c98eb2fd..40a6ffe9505 100644
--- a/src/librustdoc/visit_lib.rs
+++ b/src/librustdoc/visit_lib.rs
@@ -13,6 +13,7 @@ use rustc::middle::privacy::{AccessLevels, AccessLevel};
 use rustc::hir::def::Def;
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
 use rustc::ty::Visibility;
+use rustc::util::nodemap::FxHashSet;
 
 use std::cell::RefMut;
 
@@ -29,6 +30,8 @@ pub struct LibEmbargoVisitor<'a, 'b: 'a, 'tcx: 'b> {
     access_levels: RefMut<'a, AccessLevels<DefId>>,
     // Previous accessibility level, None means unreachable
     prev_level: Option<AccessLevel>,
+    // Keeps track of already visited modules, in case a module re-exports its parent
+    visited_mods: FxHashSet<DefId>,
 }
 
 impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> {
@@ -38,6 +41,7 @@ impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> {
             cstore: &*cx.sess().cstore,
             access_levels: cx.access_levels.borrow_mut(),
             prev_level: Some(AccessLevel::Public),
+            visited_mods: FxHashSet()
         }
     }
 
@@ -62,6 +66,10 @@ impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> {
     }
 
     pub fn visit_mod(&mut self, def_id: DefId) {
+        if !self.visited_mods.insert(def_id) {
+            return;
+        }
+
         for item in self.cstore.item_children(def_id) {
             self.visit_item(item.def);
         }
diff --git a/src/test/rustdoc/auxiliary/issue-40936.rs b/src/test/rustdoc/auxiliary/issue-40936.rs
new file mode 100644
index 00000000000..54cc18cca23
--- /dev/null
+++ b/src/test/rustdoc/auxiliary/issue-40936.rs
@@ -0,0 +1,15 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub mod outermod {
+    pub mod innermod {
+        pub use super::*;
+    }
+}
diff --git a/src/test/rustdoc/issue-40936.rs b/src/test/rustdoc/issue-40936.rs
new file mode 100644
index 00000000000..3e02eec1b9c
--- /dev/null
+++ b/src/test/rustdoc/issue-40936.rs
@@ -0,0 +1,16 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:issue-40936.rs
+// build-aux-docs
+
+#![crate_name = "foo"]
+
+extern crate issue_40936;