rustc_interface: Dismantle register_plugins query

This commit is contained in:
Vadim Petrochenkov 2023-08-07 14:23:01 +08:00
parent adb15a20ac
commit b6ac576487
5 changed files with 119 additions and 132 deletions

View file

@ -32,7 +32,7 @@ use rustc_feature::find_gated_cfg;
use rustc_fluent_macro::fluent_messages; use rustc_fluent_macro::fluent_messages;
use rustc_interface::util::{self, collect_crate_types, get_codegen_backend}; use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
use rustc_interface::{interface, Queries}; use rustc_interface::{interface, Queries};
use rustc_lint::LintStore; use rustc_lint::{unerased_lint_store, LintStore};
use rustc_metadata::locator; use rustc_metadata::locator;
use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS}; use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS};
use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType, TrimmedDefPaths}; use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType, TrimmedDefPaths};
@ -411,15 +411,11 @@ fn run_compiler(
return early_exit(); return early_exit();
} }
{ if sess.opts.describe_lints {
let plugins = queries.register_plugins()?; queries
let (.., lint_store) = &*plugins.borrow(); .global_ctxt()?
.enter(|tcx| describe_lints(sess, unerased_lint_store(tcx), true));
// Lint plugins are registered; now we can process command line flags. return early_exit();
if sess.opts.describe_lints {
describe_lints(sess, lint_store, true);
return early_exit();
}
} }
// Make sure name resolution and macro expansion is run. // Make sure name resolution and macro expansion is run.

View file

@ -12,7 +12,7 @@ use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
use rustc_errors::PResult; use rustc_errors::PResult;
use rustc_expand::base::{ExtCtxt, LintStoreExpand}; use rustc_expand::base::{ExtCtxt, LintStoreExpand};
use rustc_fs_util::try_canonicalize; use rustc_fs_util::try_canonicalize;
use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE}; use rustc_hir::def_id::LOCAL_CRATE;
use rustc_lint::{unerased_lint_store, BufferedEarlyLint, EarlyCheckNode, LintStore}; use rustc_lint::{unerased_lint_store, BufferedEarlyLint, EarlyCheckNode, LintStore};
use rustc_metadata::creader::CStore; use rustc_metadata::creader::CStore;
use rustc_middle::arena::Arena; use rustc_middle::arena::Arena;
@ -72,43 +72,16 @@ fn count_nodes(krate: &ast::Crate) -> usize {
counter.count counter.count
} }
pub fn register_plugins<'a>( pub(crate) fn create_lint_store(
sess: &'a Session, sess: &Session,
metadata_loader: &'a dyn MetadataLoader, metadata_loader: &dyn MetadataLoader,
register_lints: impl Fn(&Session, &mut LintStore), register_lints: Option<impl Fn(&Session, &mut LintStore)>,
pre_configured_attrs: &[ast::Attribute], pre_configured_attrs: &[ast::Attribute],
crate_name: Symbol, ) -> LintStore {
) -> Result<LintStore> {
// these need to be set "early" so that expansion sees `quote` if enabled.
let features = rustc_expand::config::features(sess, pre_configured_attrs);
sess.init_features(features);
let crate_types = util::collect_crate_types(sess, pre_configured_attrs);
sess.init_crate_types(crate_types);
let stable_crate_id = StableCrateId::new(
crate_name,
sess.crate_types().contains(&CrateType::Executable),
sess.opts.cg.metadata.clone(),
sess.cfg_version,
);
sess.stable_crate_id.set(stable_crate_id).expect("not yet initialized");
rustc_incremental::prepare_session_directory(sess, crate_name, stable_crate_id)?;
if sess.opts.incremental.is_some() {
sess.time("incr_comp_garbage_collect_session_directories", || {
if let Err(e) = rustc_incremental::garbage_collect_session_directories(sess) {
warn!(
"Error while trying to garbage collect incremental \
compilation cache directory: {}",
e
);
}
});
}
let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints()); let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints());
register_lints(sess, &mut lint_store); if let Some(register_lints) = register_lints {
register_lints(sess, &mut lint_store);
}
let registrars = sess.time("plugin_loading", || { let registrars = sess.time("plugin_loading", || {
plugin::load::load_plugins(sess, metadata_loader, pre_configured_attrs) plugin::load::load_plugins(sess, metadata_loader, pre_configured_attrs)
@ -120,7 +93,7 @@ pub fn register_plugins<'a>(
} }
}); });
Ok(lint_store) lint_store
} }
fn pre_expansion_lint<'a>( fn pre_expansion_lint<'a>(

View file

@ -1,6 +1,6 @@
use crate::errors::{FailedWritingFile, RustcErrorFatal, RustcErrorUnexpectedAnnotation}; use crate::errors::{FailedWritingFile, RustcErrorFatal, RustcErrorUnexpectedAnnotation};
use crate::interface::{Compiler, Result}; use crate::interface::{Compiler, Result};
use crate::passes; use crate::{passes, util};
use rustc_ast as ast; use rustc_ast as ast;
use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::traits::CodegenBackend;
@ -9,15 +9,14 @@ use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::steal::Steal; use rustc_data_structures::steal::Steal;
use rustc_data_structures::svh::Svh; use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::{AppendOnlyIndexVec, Lrc, OnceCell, RwLock, WorkerLocal}; use rustc_data_structures::sync::{AppendOnlyIndexVec, Lrc, OnceCell, RwLock, WorkerLocal};
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::def_id::{StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::definitions::Definitions; use rustc_hir::definitions::Definitions;
use rustc_incremental::DepGraphFuture; use rustc_incremental::DepGraphFuture;
use rustc_lint::LintStore;
use rustc_metadata::creader::CStore; use rustc_metadata::creader::CStore;
use rustc_middle::arena::Arena; use rustc_middle::arena::Arena;
use rustc_middle::dep_graph::DepGraph; use rustc_middle::dep_graph::DepGraph;
use rustc_middle::ty::{GlobalCtxt, TyCtxt}; use rustc_middle::ty::{GlobalCtxt, TyCtxt};
use rustc_session::config::{self, OutputFilenames, OutputType}; use rustc_session::config::{self, CrateType, OutputFilenames, OutputType};
use rustc_session::cstore::Untracked; use rustc_session::cstore::Untracked;
use rustc_session::{output::find_crate_name, Session}; use rustc_session::{output::find_crate_name, Session};
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
@ -85,12 +84,11 @@ pub struct Queries<'tcx> {
arena: WorkerLocal<Arena<'tcx>>, arena: WorkerLocal<Arena<'tcx>>,
hir_arena: WorkerLocal<rustc_hir::Arena<'tcx>>, hir_arena: WorkerLocal<rustc_hir::Arena<'tcx>>,
dep_graph_future: Query<Option<DepGraphFuture>>,
parse: Query<ast::Crate>, parse: Query<ast::Crate>,
pre_configure: Query<(ast::Crate, ast::AttrVec)>, pre_configure: Query<(ast::Crate, ast::AttrVec)>,
crate_name: Query<Symbol>, crate_name: Query<Symbol>,
register_plugins: Query<(ast::Crate, ast::AttrVec, Lrc<LintStore>)>, crate_types: Query<Vec<CrateType>>,
dep_graph: Query<DepGraph>, stable_crate_id: Query<StableCrateId>,
// This just points to what's in `gcx_cell`. // This just points to what's in `gcx_cell`.
gcx: Query<&'tcx GlobalCtxt<'tcx>>, gcx: Query<&'tcx GlobalCtxt<'tcx>>,
} }
@ -102,12 +100,11 @@ impl<'tcx> Queries<'tcx> {
gcx_cell: OnceCell::new(), gcx_cell: OnceCell::new(),
arena: WorkerLocal::new(|_| Arena::default()), arena: WorkerLocal::new(|_| Arena::default()),
hir_arena: WorkerLocal::new(|_| rustc_hir::Arena::default()), hir_arena: WorkerLocal::new(|_| rustc_hir::Arena::default()),
dep_graph_future: Default::default(),
parse: Default::default(), parse: Default::default(),
pre_configure: Default::default(), pre_configure: Default::default(),
crate_name: Default::default(), crate_name: Default::default(),
register_plugins: Default::default(), crate_types: Default::default(),
dep_graph: Default::default(), stable_crate_id: Default::default(),
gcx: Default::default(), gcx: Default::default(),
} }
} }
@ -119,13 +116,6 @@ impl<'tcx> Queries<'tcx> {
self.compiler.codegen_backend() self.compiler.codegen_backend()
} }
fn dep_graph_future(&self) -> Result<QueryResult<'_, Option<DepGraphFuture>>> {
self.dep_graph_future.compute(|| {
let sess = self.session();
Ok(sess.opts.build_dep_graph().then(|| rustc_incremental::load_dep_graph(sess)))
})
}
pub fn parse(&self) -> Result<QueryResult<'_, ast::Crate>> { pub fn parse(&self) -> Result<QueryResult<'_, ast::Crate>> {
self.parse self.parse
.compute(|| passes::parse(self.session()).map_err(|mut parse_error| parse_error.emit())) .compute(|| passes::parse(self.session()).map_err(|mut parse_error| parse_error.emit()))
@ -148,84 +138,111 @@ impl<'tcx> Queries<'tcx> {
}) })
} }
pub fn register_plugins(
&self,
) -> Result<QueryResult<'_, (ast::Crate, ast::AttrVec, Lrc<LintStore>)>> {
self.register_plugins.compute(|| {
let crate_name = *self.crate_name()?.borrow();
let (krate, pre_configured_attrs) = self.pre_configure()?.steal();
let empty: &(dyn Fn(&Session, &mut LintStore) + Sync + Send) = &|_, _| {};
let lint_store = passes::register_plugins(
self.session(),
&*self.codegen_backend().metadata_loader(),
self.compiler.register_lints.as_deref().unwrap_or_else(|| empty),
&pre_configured_attrs,
crate_name,
)?;
// Compute the dependency graph (in the background). We want to do
// this as early as possible, to give the DepGraph maximum time to
// load before dep_graph() is called, but it also can't happen
// until after rustc_incremental::prepare_session_directory() is
// called, which happens within passes::register_plugins().
self.dep_graph_future().ok();
Ok((krate, pre_configured_attrs, Lrc::new(lint_store)))
})
}
fn crate_name(&self) -> Result<QueryResult<'_, Symbol>> { fn crate_name(&self) -> Result<QueryResult<'_, Symbol>> {
self.crate_name.compute(|| { self.crate_name.compute(|| {
Ok({ let pre_configure_result = self.pre_configure()?;
let pre_configure_result = self.pre_configure()?; let (_, pre_configured_attrs) = &*pre_configure_result.borrow();
let (_, pre_configured_attrs) = &*pre_configure_result.borrow(); // parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches.
// parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches. Ok(find_crate_name(self.session(), pre_configured_attrs))
find_crate_name(self.session(), pre_configured_attrs)
})
}) })
} }
fn dep_graph(&self) -> Result<QueryResult<'_, DepGraph>> { fn crate_types(&self) -> Result<QueryResult<'_, Vec<CrateType>>> {
self.dep_graph.compute(|| { self.crate_types.compute(|| {
let sess = self.session(); let pre_configure_result = self.pre_configure()?;
let future_opt = self.dep_graph_future()?.steal(); let (_, pre_configured_attrs) = &*pre_configure_result.borrow();
let dep_graph = future_opt Ok(util::collect_crate_types(&self.session(), &pre_configured_attrs))
.and_then(|future| {
let (prev_graph, mut prev_work_products) =
sess.time("blocked_on_dep_graph_loading", || future.open().open(sess));
// Convert from UnordMap to FxIndexMap by sorting
let prev_work_product_ids =
prev_work_products.items().map(|x| *x.0).into_sorted_stable_ord();
let prev_work_products = prev_work_product_ids
.into_iter()
.map(|x| (x, prev_work_products.remove(&x).unwrap()))
.collect::<FxIndexMap<_, _>>();
rustc_incremental::build_dep_graph(sess, prev_graph, prev_work_products)
})
.unwrap_or_else(DepGraph::new_disabled);
Ok(dep_graph)
}) })
} }
fn stable_crate_id(&self) -> Result<QueryResult<'_, StableCrateId>> {
self.stable_crate_id.compute(|| {
let sess = self.session();
Ok(StableCrateId::new(
*self.crate_name()?.borrow(),
self.crate_types()?.borrow().contains(&CrateType::Executable),
sess.opts.cg.metadata.clone(),
sess.cfg_version,
))
})
}
fn dep_graph_future(&self) -> Result<Option<DepGraphFuture>> {
let sess = self.session();
let crate_name = *self.crate_name()?.borrow();
let stable_crate_id = *self.stable_crate_id()?.borrow();
// `load_dep_graph` can only be called after `prepare_session_directory`.
rustc_incremental::prepare_session_directory(sess, crate_name, stable_crate_id)?;
let res = sess.opts.build_dep_graph().then(|| rustc_incremental::load_dep_graph(sess));
if sess.opts.incremental.is_some() {
sess.time("incr_comp_garbage_collect_session_directories", || {
if let Err(e) = rustc_incremental::garbage_collect_session_directories(sess) {
warn!(
"Error while trying to garbage collect incremental \
compilation cache directory: {}",
e
);
}
});
}
Ok(res)
}
fn dep_graph(&self, dep_graph_future: Option<DepGraphFuture>) -> DepGraph {
dep_graph_future
.and_then(|future| {
let sess = self.session();
let (prev_graph, mut prev_work_products) =
sess.time("blocked_on_dep_graph_loading", || future.open().open(sess));
// Convert from UnordMap to FxIndexMap by sorting
let prev_work_product_ids =
prev_work_products.items().map(|x| *x.0).into_sorted_stable_ord();
let prev_work_products = prev_work_product_ids
.into_iter()
.map(|x| (x, prev_work_products.remove(&x).unwrap()))
.collect::<FxIndexMap<_, _>>();
rustc_incremental::build_dep_graph(sess, prev_graph, prev_work_products)
})
.unwrap_or_else(DepGraph::new_disabled)
}
pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, &'tcx GlobalCtxt<'tcx>>> { pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, &'tcx GlobalCtxt<'tcx>>> {
self.gcx.compute(|| { self.gcx.compute(|| {
let crate_name = *self.crate_name()?.borrow(); // Compute the dependency graph (in the background). We want to do this as early as
let (krate, pre_configured_attrs, lint_store) = self.register_plugins()?.steal(); // possible, to give the DepGraph maximum time to load before `dep_graph` is called.
let dep_graph_future = self.dep_graph_future()?;
let crate_name = self.crate_name()?.steal();
let crate_types = self.crate_types()?.steal();
let stable_crate_id = self.stable_crate_id()?.steal();
let (krate, pre_configured_attrs) = self.pre_configure()?.steal();
let sess = self.session(); let sess = self.session();
let lint_store = Lrc::new(passes::create_lint_store(
let cstore = RwLock::new(Box::new(CStore::new(sess)) as _); sess,
let definitions = RwLock::new(Definitions::new(sess.local_stable_crate_id())); &*self.codegen_backend().metadata_loader(),
self.compiler.register_lints.as_deref(),
&pre_configured_attrs,
));
let cstore = RwLock::new(Box::new(CStore::new(stable_crate_id)) as _);
let definitions = RwLock::new(Definitions::new(stable_crate_id));
let source_span = AppendOnlyIndexVec::new(); let source_span = AppendOnlyIndexVec::new();
let _id = source_span.push(krate.spans.inner_span); let _id = source_span.push(krate.spans.inner_span);
debug_assert_eq!(_id, CRATE_DEF_ID); debug_assert_eq!(_id, CRATE_DEF_ID);
let untracked = Untracked { cstore, source_span, definitions }; let untracked = Untracked { cstore, source_span, definitions };
// FIXME: Move these fields from session to tcx and make them immutable.
sess.init_crate_types(crate_types);
sess.stable_crate_id.set(stable_crate_id).expect("not yet initialized");
sess.init_features(rustc_expand::config::features(sess, &pre_configured_attrs));
let qcx = passes::create_global_ctxt( let qcx = passes::create_global_ctxt(
self.compiler, self.compiler,
lint_store, lint_store,
self.dep_graph()?.steal(), self.dep_graph(dep_graph_future),
untracked, untracked,
&self.gcx_cell, &self.gcx_cell,
&self.arena, &self.arena,

View file

@ -20,7 +20,6 @@ use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate};
use rustc_session::lint; use rustc_session::lint;
use rustc_session::output::validate_crate_name; use rustc_session::output::validate_crate_name;
use rustc_session::search_paths::PathKind; use rustc_session::search_paths::PathKind;
use rustc_session::Session;
use rustc_span::edition::Edition; use rustc_span::edition::Edition;
use rustc_span::symbol::{sym, Symbol}; use rustc_span::symbol::{sym, Symbol};
use rustc_span::{Span, DUMMY_SP}; use rustc_span::{Span, DUMMY_SP};
@ -262,9 +261,9 @@ impl CStore {
} }
} }
pub fn new(sess: &Session) -> CStore { pub fn new(local_stable_crate_id: StableCrateId) -> CStore {
let mut stable_crate_ids = StableCrateIdMap::default(); let mut stable_crate_ids = StableCrateIdMap::default();
stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE); stable_crate_ids.insert(local_stable_crate_id, LOCAL_CRATE);
CStore { CStore {
// We add an empty entry for LOCAL_CRATE (which maps to zero) in // We add an empty entry for LOCAL_CRATE (which maps to zero) in
// order to make array indices in `metas` match with the // order to make array indices in `metas` match with the
@ -544,6 +543,9 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
self.sess, self.sess,
&**metadata_loader, &**metadata_loader,
name, name,
// The all loop is because `--crate-type=rlib --crate-type=rlib` is
// legal and produces both inside this type.
self.sess.crate_types().iter().all(|c| *c == CrateType::Rlib),
hash, hash,
extra_filename, extra_filename,
false, // is_host false, // is_host

View file

@ -222,7 +222,7 @@ use rustc_data_structures::owned_slice::slice_owned;
use rustc_data_structures::svh::Svh; use rustc_data_structures::svh::Svh;
use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg}; use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg};
use rustc_fs_util::try_canonicalize; use rustc_fs_util::try_canonicalize;
use rustc_session::config::{self, CrateType}; use rustc_session::config;
use rustc_session::cstore::{CrateSource, MetadataLoader}; use rustc_session::cstore::{CrateSource, MetadataLoader};
use rustc_session::filesearch::FileSearch; use rustc_session::filesearch::FileSearch;
use rustc_session::search_paths::PathKind; use rustc_session::search_paths::PathKind;
@ -305,14 +305,12 @@ impl<'a> CrateLocator<'a> {
sess: &'a Session, sess: &'a Session,
metadata_loader: &'a dyn MetadataLoader, metadata_loader: &'a dyn MetadataLoader,
crate_name: Symbol, crate_name: Symbol,
is_rlib: bool,
hash: Option<Svh>, hash: Option<Svh>,
extra_filename: Option<&'a str>, extra_filename: Option<&'a str>,
is_host: bool, is_host: bool,
path_kind: PathKind, path_kind: PathKind,
) -> CrateLocator<'a> { ) -> CrateLocator<'a> {
// The all loop is because `--crate-type=rlib --crate-type=rlib` is
// legal and produces both inside this type.
let is_rlib = sess.crate_types().iter().all(|c| *c == CrateType::Rlib);
let needs_object_code = sess.opts.output_types.should_codegen(); let needs_object_code = sess.opts.output_types.should_codegen();
// If we're producing an rlib, then we don't need object code. // If we're producing an rlib, then we don't need object code.
// Or, if we're not producing object code, then we don't need it either // Or, if we're not producing object code, then we don't need it either
@ -883,9 +881,10 @@ fn find_plugin_registrar_impl<'a>(
sess, sess,
metadata_loader, metadata_loader,
name, name,
None, // hash false, // is_rlib
None, // extra_filename None, // hash
true, // is_host None, // extra_filename
true, // is_host
PathKind::Crate, PathKind::Crate,
); );