Change:
// 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");

Discussion:
/cc
So the explosion is that somehow the crate index in the is broken, or at least not entirely right. Interestingly if you add to the then it no longer ICEs (but has the same ) Edit: So this looks like it's somehow a bug when trying to resolve it as a global name (both and prevent the iCE)
Maybe it's linked to ? If so, it's not in rustdoc but below.
I believe I've worked out approximately what's going on: Rustdoc freezes the compiler state (resolver, etc) as part of the setup to ready the instance. Since was made optional, and crate names are automatically part of the global scope, people stopped necessarily telling the compiler about the crates in their code. If a comment references a path in this manner, but the code itself doesn't, then the resolver frozen into the doesn't have that crate's metadata loaded into it. When we then ask the resolver to resolve a new path (e.g. ) it goes ahead and loads the crate into a different instance of the than will be used when we then try and use the later. It feels like the moment a is d it should also be locked so that it can never be modified again. It's also possible that rustdoc could be forced to enter the right context so that we never do this wrongly, but that's beyond me right now. Given that, , I feel this is probably either a bug in how is handling the resolver, or else a change in how the resolver behaves which either needs fixing, or changing in to cope.
My gut feeling is that we probably need to stop capturing/cloning the resolver as we do here: and instead try and find a resolver as part of the closure here: Of course, it looks like a has an immutable copy of the resolver's outputs, and no access to the resolver itself, urgh, and we have no easy way to inject changes into the context at this point.
I wonder why that type can be cloned in the first place...

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: