resolve: Don't speculatively load crates if this is a speculative resolution

This avoids a rare rustdoc bug where loading `core` twice caused a
'cannot find a built-in macro' error:

1. `x.py build --stage 1` builds the standard library and creates a sysroot
2. `cargo doc` does something like `cargo check` to create `rmeta`s for all the crates (unrelated to what was built above)
3. the `cargo check`-like `libcore-*.rmeta` is loaded as a transitive dependency *and claims ownership* of builtin macros
4. `rustdoc` later tries to resolve some path in a doc link
5. suggestion logic fires and loads "extern prelude" crates by name
6. the sysroot `libcore-*.rlib` is loaded and *fails to claim ownership* of builtin macros

This fixes step 5. by not running suggestion logic if this is a
speculative resolution. Additionally, it marks `resolve_ast_path` as a
speculative resolution.
This commit is contained in:
Joshua Nelson 2020-08-29 09:47:39 -04:00
parent a1c71a1709
commit 9131d23cc0

View File

@ -2385,8 +2385,12 @@ impl<'a> Resolver<'a> {
Res::Def(DefKind::Mod, _) => true,
_ => false,
};
let mut candidates =
self.lookup_import_candidates(ident, TypeNS, parent_scope, is_mod);
// Don't look up import candidates if this is a speculative resolve
let mut candidates = if record_used {
self.lookup_import_candidates(ident, TypeNS, parent_scope, is_mod)
} else {
Vec::new()
};
candidates.sort_by_cached_key(|c| {
(c.path.segments.len(), pprust::path_to_string(&c.path))
});
@ -3200,7 +3204,7 @@ impl<'a> Resolver<'a> {
&Segment::from_path(path),
Some(ns),
parent_scope,
true,
false,
path.span,
CrateLint::No,
) {