Change:
I found an ICE when trying to document the [spirit-log][1] crate on the latest . Skimming through the backtrace, it looks like accessed an invalid index while traversing links within . Steps to reproduce: [1]:
Taking a look.
Actually, it's failing outside of rustdoc so I prefer to let someone else handle it. cc
I think this might be a bug (or at least mismatch between how uses the resolver infrastructure and how it's meant to work). See my comment here:

Discussion:
/// Extracts `--extern CRATE=PATH` arguments from `matches` and /// returns a map mapping crate names to their paths or else an /// error message. <ins> /// Also handles `--extern-private` which for the purposes of rustdoc /// we can treat as `--extern` </ins> // FIXME(eddyb) This shouldn't be duplicated with `rustc::session`. fn parse_externs(matches: &getopts::Matches) -> Result<Externs, String> { let mut externs: BTreeMap<_, ExternEntry> = BTreeMap::new(); <del> for arg in &matches.opt_strs("extern") { </del> <ins> for arg in matches.opt_strs("extern").iter().chain(matches.opt_strs("extern-private").iter()) { </ins> 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());

use rustc_lint; use rustc::session::{self, config}; <ins> use rustc::hir::def::Namespace::TypeNS; </ins> use rustc::hir::def_id::{DefId, DefIndex, CrateNum, LOCAL_CRATE}; use rustc::hir::HirId; use rustc::middle::cstore::CrateStore;

use rustc_driver::abort_on_err; use rustc_resolve as resolve; <ins> use syntax::ast::CRATE_NODE_ID; </ins> use syntax::source_map; use syntax::attr; use syntax::feature_gate::UnstableFeatures; use syntax::json::JsonEmitter; use syntax::symbol::sym; <ins> use syntax_pos::DUMMY_SP; </ins> use errors; use errors::emitter::{Emitter, EmitterWriter};

.. } = options; <ins> let extern_names: Vec<String> = externs.iter().map(|(s,_)| s).cloned().collect(); </ins> // Add the rustdoc cfg into the doc build. cfgs.push("rustdoc".to_string());

// 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. <del> let resolver = abort_on_err(compiler.expansion(), sess).peek().1.borrow().clone(); </del> <ins> 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() }; </ins> if sess.has_errors() { sess.fatal("Compilation failed, aborting rustdoc");

stable("extern", |o| { o.optmulti("", "extern", "pass an --extern to rustc", "NAME=PATH") }), <ins> stable("extern-private", |o| { o.optmulti("", "extern-private", "pass an --extern to rustc (compatibility only)", "NAME=PATH") }), </ins> unstable("extern-html-root-url", |o| { o.optmulti("", "extern-html-root-url", "base URL to use for dependencies", "NAME=URL")

<ins> /// This will be referred to by the test docstring pub struct Something; </ins>

<ins> // 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] </ins>