From 9131d23cc0fb5461050bc19e40a3858b61487069 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 29 Aug 2020 09:47:39 -0400 Subject: [PATCH] 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. --- src/librustc_resolve/lib.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index f2319bfe64de8..5892edf7652b7 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -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, ) {