From d2b30f7d3883a9f5d2e419d3d2c86cb66e9d3410 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 23 Sep 2014 15:13:56 -0700 Subject: [PATCH 1/2] rustdoc: Prevent infinite recursion when inlining Cyclic pub-use chains triggered infinite recursion, and this commit adds a hash set to guard against cyclic recursion. This will cause one of the reexports to render as a `pub use` instead of inlining the documentation. Closes #16274 --- src/librustdoc/visit_ast.rs | 11 +++++++-- src/test/run-make/rustdoc-recursion/Makefile | 10 ++++++++ src/test/run-make/rustdoc-recursion/foo.rs | 25 ++++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 src/test/run-make/rustdoc-recursion/Makefile create mode 100644 src/test/run-make/rustdoc-recursion/foo.rs diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index a9e0c9cb260f6..06b79b18d1018 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -11,6 +11,8 @@ //! Rust AST Visitor. Extracts useful information and massages it into a form //! usable for clean +use std::collections::HashSet; + use syntax::abi; use syntax::ast; use syntax::ast_util; @@ -38,6 +40,7 @@ pub struct RustdocVisitor<'a, 'tcx: 'a> { pub attrs: Vec, pub cx: &'a core::DocContext<'tcx>, pub analysis: Option<&'a core::CrateAnalysis>, + view_item_stack: HashSet, } impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { @@ -48,6 +51,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { attrs: Vec::new(), cx: cx, analysis: analysis, + view_item_stack: HashSet::new(), } } @@ -228,8 +232,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { if !please_inline && analysis.public_items.contains(&def.node) { return false } + if !self.view_item_stack.insert(id) { return false } - match tcx.map.get(def.node) { + let ret = match tcx.map.get(def.node) { ast_map::NodeItem(it) => { if glob { match it.node { @@ -249,7 +254,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { true } _ => false, - } + }; + self.view_item_stack.remove(&id); + return ret; } pub fn visit_item(&mut self, item: &ast::Item, diff --git a/src/test/run-make/rustdoc-recursion/Makefile b/src/test/run-make/rustdoc-recursion/Makefile new file mode 100644 index 0000000000000..97c0385828d77 --- /dev/null +++ b/src/test/run-make/rustdoc-recursion/Makefile @@ -0,0 +1,10 @@ +-include ../tools.mk + +# FIXME ignore windows +ifndef IS_WINDOWS +all: + $(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc foo.rs +else +all: +endif + diff --git a/src/test/run-make/rustdoc-recursion/foo.rs b/src/test/run-make/rustdoc-recursion/foo.rs new file mode 100644 index 0000000000000..05f11205b7113 --- /dev/null +++ b/src/test/run-make/rustdoc-recursion/foo.rs @@ -0,0 +1,25 @@ +// Copyright 2012-2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "lib"] +#![feature(globs)] + +mod m { + pub use self::a::Foo; + + mod a { + pub struct Foo; + } + + mod b { + pub use super::*; + } +} + From 3d8ca595a158dbf4ffbaece479e75b9c811ce815 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 23 Sep 2014 15:19:30 -0700 Subject: [PATCH 2/2] rustdoc: Don't try to inline the crate root Fixes other test cases found in #16274 --- src/librustdoc/visit_ast.rs | 7 ++++-- src/test/run-make/rustdoc-recursion/Makefile | 2 ++ src/test/run-make/rustdoc-recursion/foo.rs | 2 +- src/test/run-make/rustdoc-recursion/foo2.rs | 24 +++++++++++++++++++ src/test/run-make/rustdoc-recursion/foo3.rs | 25 ++++++++++++++++++++ 5 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 src/test/run-make/rustdoc-recursion/foo2.rs create mode 100644 src/test/run-make/rustdoc-recursion/foo3.rs diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 06b79b18d1018..d4a1a35790936 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -46,12 +46,15 @@ pub struct RustdocVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { pub fn new(cx: &'a core::DocContext<'tcx>, analysis: Option<&'a core::CrateAnalysis>) -> RustdocVisitor<'a, 'tcx> { + // If the root is reexported, terminate all recursion. + let mut stack = HashSet::new(); + stack.insert(ast::CRATE_NODE_ID); RustdocVisitor { module: Module::new(None), attrs: Vec::new(), cx: cx, analysis: analysis, - view_item_stack: HashSet::new(), + view_item_stack: stack, } } @@ -232,7 +235,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { if !please_inline && analysis.public_items.contains(&def.node) { return false } - if !self.view_item_stack.insert(id) { return false } + if !self.view_item_stack.insert(def.node) { return false } let ret = match tcx.map.get(def.node) { ast_map::NodeItem(it) => { diff --git a/src/test/run-make/rustdoc-recursion/Makefile b/src/test/run-make/rustdoc-recursion/Makefile index 97c0385828d77..b7fc6d6c0ad5b 100644 --- a/src/test/run-make/rustdoc-recursion/Makefile +++ b/src/test/run-make/rustdoc-recursion/Makefile @@ -4,6 +4,8 @@ ifndef IS_WINDOWS all: $(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc foo.rs + $(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc foo2.rs + $(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc foo3.rs else all: endif diff --git a/src/test/run-make/rustdoc-recursion/foo.rs b/src/test/run-make/rustdoc-recursion/foo.rs index 05f11205b7113..29a909f139ead 100644 --- a/src/test/run-make/rustdoc-recursion/foo.rs +++ b/src/test/run-make/rustdoc-recursion/foo.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/test/run-make/rustdoc-recursion/foo2.rs b/src/test/run-make/rustdoc-recursion/foo2.rs new file mode 100644 index 0000000000000..7505d20566dbb --- /dev/null +++ b/src/test/run-make/rustdoc-recursion/foo2.rs @@ -0,0 +1,24 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "lib"] +#![feature(globs)] + +mod m { + pub use self::a::Foo; + + mod a { + pub struct Foo; + } + + mod b { + pub use super::*; + } +} diff --git a/src/test/run-make/rustdoc-recursion/foo3.rs b/src/test/run-make/rustdoc-recursion/foo3.rs new file mode 100644 index 0000000000000..62a13f76ca4f0 --- /dev/null +++ b/src/test/run-make/rustdoc-recursion/foo3.rs @@ -0,0 +1,25 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(globs)] + +pub mod longhands { + pub use super::*; + + pub use super::common_types::computed::compute_CSSColor as to_computed_value; + + pub fn computed_as_specified() {} +} + +pub mod common_types { + pub mod computed { + pub use super::super::longhands::computed_as_specified as compute_CSSColor; + } +}