Auto merge of #90489 - jyn514:load-all-extern-crates, r=petrochenkov
rustdoc: Go back to loading all external crates unconditionally This *continues* to cause regressions. This code will be unnecessary once access to the resolver happens fully before creating the tyctxt (#83761), so load all crates unconditionally for now. To minimize churn, this leaves in the code for loading crates selectively. "Fixes" https://github.com/rust-lang/rust/issues/84738. Previously: https://github.com/rust-lang/rust/pull/83738, https://github.com/rust-lang/rust/pull/85749, https://github.com/rust-lang/rust/pull/88215 r? `@petrochenkov` cc `@camelid` (this should fix the "index out of bounds" error you had while looking up `crate_name`).
This commit is contained in:
commit
14a2fd640e
8 changed files with 93 additions and 7 deletions
|
@ -16,13 +16,15 @@ use rustc_middle::hir::map::Map;
|
|||
use rustc_middle::middle::privacy::AccessLevels;
|
||||
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
|
||||
use rustc_resolve as resolve;
|
||||
use rustc_resolve::Namespace::TypeNS;
|
||||
use rustc_session::config::{self, CrateType, ErrorOutputType};
|
||||
use rustc_session::lint;
|
||||
use rustc_session::DiagnosticOutput;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::def_id::CRATE_DEF_INDEX;
|
||||
use rustc_span::source_map;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::lazy::SyncLazy;
|
||||
|
@ -283,13 +285,43 @@ crate fn create_config(
|
|||
}
|
||||
|
||||
crate fn create_resolver<'a>(
|
||||
externs: config::Externs,
|
||||
queries: &Queries<'a>,
|
||||
sess: &Session,
|
||||
) -> Rc<RefCell<interface::BoxedResolver>> {
|
||||
let (krate, resolver, _) = &*abort_on_err(queries.expansion(), sess).peek();
|
||||
let resolver = resolver.clone();
|
||||
|
||||
crate::passes::collect_intra_doc_links::load_intra_link_crates(resolver, krate)
|
||||
let resolver = crate::passes::collect_intra_doc_links::load_intra_link_crates(resolver, krate);
|
||||
|
||||
// FIXME: somehow rustdoc is still missing crates even though we loaded all
|
||||
// the known necessary crates. Load them all unconditionally until we find a way to fix this.
|
||||
// DO NOT REMOVE THIS without first testing on the reproducer in
|
||||
// https://github.com/jyn514/objr/commit/edcee7b8124abf0e4c63873e8422ff81beb11ebb
|
||||
let extern_names: Vec<String> = externs
|
||||
.iter()
|
||||
.filter(|(_, entry)| entry.add_prelude)
|
||||
.map(|(name, _)| name)
|
||||
.cloned()
|
||||
.collect();
|
||||
resolver.borrow_mut().access(|resolver| {
|
||||
sess.time("load_extern_crates", || {
|
||||
for extern_name in &extern_names {
|
||||
debug!("loading extern crate {}", extern_name);
|
||||
if let Err(()) = resolver
|
||||
.resolve_str_path_error(
|
||||
DUMMY_SP,
|
||||
extern_name,
|
||||
TypeNS,
|
||||
LocalDefId { local_def_index: CRATE_DEF_INDEX }.to_def_id(),
|
||||
) {
|
||||
warn!("unable to resolve external crate {} (do you have an unused `--extern` crate?)", extern_name)
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
resolver
|
||||
}
|
||||
|
||||
crate fn run_global_ctxt(
|
||||
|
|
|
@ -756,6 +756,7 @@ fn main_options(options: config::Options) -> MainResult {
|
|||
let default_passes = options.default_passes;
|
||||
let output_format = options.output_format;
|
||||
// FIXME: fix this clone (especially render_options)
|
||||
let externs = options.externs.clone();
|
||||
let manual_passes = options.manual_passes.clone();
|
||||
let render_options = options.render_options.clone();
|
||||
let scrape_examples_options = options.scrape_examples_options.clone();
|
||||
|
@ -774,7 +775,7 @@ fn main_options(options: config::Options) -> MainResult {
|
|||
// 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 = core::create_resolver(queries, sess);
|
||||
let resolver = core::create_resolver(externs, queries, sess);
|
||||
|
||||
if sess.diagnostic().has_errors_or_lint_errors() {
|
||||
sess.fatal("Compilation failed, aborting rustdoc");
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use ast::visit;
|
||||
use rustc_ast as ast;
|
||||
use rustc_hir::def::Namespace::TypeNS;
|
||||
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
|
||||
|
@ -16,7 +17,7 @@ crate fn load_intra_link_crates(resolver: Resolver, krate: &ast::Crate) -> Resol
|
|||
let mut loader = IntraLinkCrateLoader { current_mod: CRATE_DEF_ID, resolver };
|
||||
// `walk_crate` doesn't visit the crate itself for some reason.
|
||||
loader.load_links_in_attrs(&krate.attrs, krate.span);
|
||||
ast::visit::walk_crate(&mut loader, krate);
|
||||
visit::walk_crate(&mut loader, krate);
|
||||
loader.resolver
|
||||
}
|
||||
|
||||
|
@ -54,7 +55,12 @@ impl IntraLinkCrateLoader {
|
|||
}
|
||||
}
|
||||
|
||||
impl ast::visit::Visitor<'_> for IntraLinkCrateLoader {
|
||||
impl visit::Visitor<'_> for IntraLinkCrateLoader {
|
||||
fn visit_foreign_item(&mut self, item: &ast::ForeignItem) {
|
||||
self.load_links_in_attrs(&item.attrs, item.span);
|
||||
visit::walk_foreign_item(self, item)
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, item: &ast::Item) {
|
||||
use rustc_ast_lowering::ResolverAstLowering;
|
||||
|
||||
|
@ -64,12 +70,29 @@ impl ast::visit::Visitor<'_> for IntraLinkCrateLoader {
|
|||
let old_mod = mem::replace(&mut self.current_mod, new_mod);
|
||||
|
||||
self.load_links_in_attrs(&item.attrs, item.span);
|
||||
ast::visit::walk_item(self, item);
|
||||
visit::walk_item(self, item);
|
||||
|
||||
self.current_mod = old_mod;
|
||||
} else {
|
||||
self.load_links_in_attrs(&item.attrs, item.span);
|
||||
ast::visit::walk_item(self, item);
|
||||
visit::walk_item(self, item);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: if doc-comments are ever allowed on function parameters, this will have to implement `visit_param` too.
|
||||
|
||||
fn visit_assoc_item(&mut self, item: &ast::AssocItem, ctxt: visit::AssocCtxt) {
|
||||
self.load_links_in_attrs(&item.attrs, item.span);
|
||||
visit::walk_assoc_item(self, item, ctxt)
|
||||
}
|
||||
|
||||
fn visit_field_def(&mut self, field: &ast::FieldDef) {
|
||||
self.load_links_in_attrs(&field.attrs, field.span);
|
||||
visit::walk_field_def(self, field)
|
||||
}
|
||||
|
||||
fn visit_variant(&mut self, v: &ast::Variant) {
|
||||
self.load_links_in_attrs(&v.attrs, v.span);
|
||||
visit::walk_variant(self, v)
|
||||
}
|
||||
}
|
||||
|
|
1
src/test/rustdoc-ui/intra-doc/auxiliary/dep1.rs
Normal file
1
src/test/rustdoc-ui/intra-doc/auxiliary/dep1.rs
Normal file
|
@ -0,0 +1 @@
|
|||
// intentionally empty
|
1
src/test/rustdoc-ui/intra-doc/auxiliary/dep2.rs
Normal file
1
src/test/rustdoc-ui/intra-doc/auxiliary/dep2.rs
Normal file
|
@ -0,0 +1 @@
|
|||
// intentionally empty
|
1
src/test/rustdoc-ui/intra-doc/auxiliary/dep3.rs
Normal file
1
src/test/rustdoc-ui/intra-doc/auxiliary/dep3.rs
Normal file
|
@ -0,0 +1 @@
|
|||
// intentionally empty
|
1
src/test/rustdoc-ui/intra-doc/auxiliary/dep4.rs
Normal file
1
src/test/rustdoc-ui/intra-doc/auxiliary/dep4.rs
Normal file
|
@ -0,0 +1 @@
|
|||
// intentionally empty
|
26
src/test/rustdoc-ui/intra-doc/extern-crate-load.rs
Normal file
26
src/test/rustdoc-ui/intra-doc/extern-crate-load.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
// check-pass
|
||||
// aux-crate:dep1=dep1.rs
|
||||
// aux-crate:dep2=dep2.rs
|
||||
// aux-crate:dep3=dep3.rs
|
||||
// aux-crate:dep4=dep4.rs
|
||||
#![deny(rustdoc::broken_intra_doc_links)]
|
||||
|
||||
pub trait Trait {
|
||||
/// [dep1]
|
||||
type Item;
|
||||
}
|
||||
|
||||
pub struct S {
|
||||
/// [dep2]
|
||||
pub x: usize,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
/// [dep3]
|
||||
pub fn printf();
|
||||
}
|
||||
|
||||
pub enum E {
|
||||
/// [dep4]
|
||||
A
|
||||
}
|
Loading…
Add table
Reference in a new issue