From 2c33568a77cf308c91129e0f0a4d4d53f1689ebb Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Fri, 8 Nov 2019 07:29:08 +0000 Subject: [PATCH 1/2] rustdoc: Support --extern-private but treat as --extern This makes `rustdoc` support `--extern-private` but treats it the same as `--extern` which is useful for making the CLI more similar to `rustc` to ease test suite integration. Signed-off-by: Daniel Silverstone --- src/librustdoc/config.rs | 4 +++- src/librustdoc/lib.rs | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 0b8d4d6c302f1..fc043cae5415a 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -608,10 +608,12 @@ fn parse_extern_html_roots( /// Extracts `--extern CRATE=PATH` arguments from `matches` and /// returns a map mapping crate names to their paths or else an /// error message. +/// Also handles `--extern-private` which for the purposes of rustdoc +/// we can treat as `--extern` // FIXME(eddyb) This shouldn't be duplicated with `rustc::session`. fn parse_externs(matches: &getopts::Matches) -> Result { let mut externs: BTreeMap<_, ExternEntry> = BTreeMap::new(); - for arg in &matches.opt_strs("extern") { + for arg in matches.opt_strs("extern").iter().chain(matches.opt_strs("extern-private").iter()) { let mut parts = arg.splitn(2, '='); let name = parts.next().ok_or("--extern value must not be empty".to_string())?; let location = parts.next().map(|s| s.to_string()); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 8cd32a3d1b508..3571104a3d90f 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -142,6 +142,10 @@ fn opts() -> Vec { stable("extern", |o| { o.optmulti("", "extern", "pass an --extern to rustc", "NAME=PATH") }), + stable("extern-private", |o| { + o.optmulti("", "extern-private", + "pass an --extern to rustc (compatibility only)", "NAME=PATH") + }), unstable("extern-html-root-url", |o| { o.optmulti("", "extern-html-root-url", "base URL to use for dependencies", "NAME=URL") From 33ded3ec7f5dbc133f9371b101310ea606663762 Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Thu, 7 Nov 2019 23:53:56 +0000 Subject: [PATCH 2/2] rustdoc: Deliberately load extern crates before processing docs In order that we can successfully later resolve paths in crates which weren't loaded as a result of merely parsing the crate we're documenting, we force the resolution of the path to each crate before cloning the resolver to use later. Closes #66159 Signed-off-by: Daniel Silverstone --- src/librustdoc/core.rs | 25 ++++++++++++++++++++- src/test/rustdoc/auxiliary/issue-66159-1.rs | 2 ++ src/test/rustdoc/issue-66159.rs | 10 +++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 src/test/rustdoc/auxiliary/issue-66159-1.rs create mode 100644 src/test/rustdoc/issue-66159.rs diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index b227f432a4e98..6047d3f2753b8 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -1,5 +1,6 @@ use rustc_lint; use rustc::session::{self, config}; +use rustc::hir::def::Namespace::TypeNS; use rustc::hir::def_id::{DefId, DefIndex, CrateNum, LOCAL_CRATE}; use rustc::hir::HirId; use rustc::middle::cstore::CrateStore; @@ -13,11 +14,13 @@ use rustc_interface::interface; use rustc_driver::abort_on_err; use rustc_resolve as resolve; +use syntax::ast::CRATE_NODE_ID; use syntax::source_map; use syntax::attr; use syntax::feature_gate::UnstableFeatures; use syntax::json::JsonEmitter; use syntax::symbol::sym; +use syntax_pos::DUMMY_SP; use errors; use errors::emitter::{Emitter, EmitterWriter}; @@ -246,6 +249,8 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt .. } = options; + let extern_names: Vec = externs.iter().map(|(s,_)| s).cloned().collect(); + // Add the rustdoc cfg into the doc build. cfgs.push("rustdoc".to_string()); @@ -343,7 +348,25 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt // We need to hold on to the complete resolver, so we cause everything to be // cloned for the analysis passes to use. Suboptimal, but necessary in the // current architecture. - let resolver = abort_on_err(compiler.expansion(), sess).peek().1.borrow().clone(); + let resolver = { + let parts = abort_on_err(compiler.expansion(), sess).peek(); + let resolver = parts.1.borrow(); + + // Before we actually clone it, let's force all the extern'd crates to + // actually be loaded, just in case they're only referred to inside + // intra-doc-links + resolver.borrow_mut().access(|resolver| { + for extern_name in &extern_names { + resolver.resolve_str_path_error(DUMMY_SP, extern_name, TypeNS, CRATE_NODE_ID) + .unwrap_or_else( + |()| panic!("Unable to resolve external crate {}", extern_name) + ); + } + }); + + // Now we're good to clone the resolver because everything should be loaded + resolver.clone() + }; if sess.has_errors() { sess.fatal("Compilation failed, aborting rustdoc"); diff --git a/src/test/rustdoc/auxiliary/issue-66159-1.rs b/src/test/rustdoc/auxiliary/issue-66159-1.rs new file mode 100644 index 0000000000000..2f3d069bd51c3 --- /dev/null +++ b/src/test/rustdoc/auxiliary/issue-66159-1.rs @@ -0,0 +1,2 @@ +/// This will be referred to by the test docstring +pub struct Something; diff --git a/src/test/rustdoc/issue-66159.rs b/src/test/rustdoc/issue-66159.rs new file mode 100644 index 0000000000000..88eca7338707c --- /dev/null +++ b/src/test/rustdoc/issue-66159.rs @@ -0,0 +1,10 @@ +// aux-build:issue-66159-1.rs +// extern-private:issue_66159_1 + +// The issue was an ICE which meant that we never actually generated the docs +// so if we have generated the docs, we're okay. +// Since we don't generate the docs for the auxilliary files, we can't actually +// verify that the struct is linked correctly. + +// @has issue_66159/index.html +//! [issue_66159_1::Something]