Rollup merge of #66791 - cjgillot:arena, r=Mark-Simulacrum
Handle GlobalCtxt directly from librustc_interface query system This PR constructs the `GlobalCtxt` as a member of the `Queries` in librustc_interface. This simplifies the code to construct it, at the expense of added complexity in the query control flow. This allows to handle the arenas directly from librustc_interface. Based on #66707 r? @Zoxc
This commit is contained in:
commit
6ea1df2340
10 changed files with 348 additions and 276 deletions
|
|
@ -93,6 +93,7 @@ macro_rules! arena_types {
|
|||
rustc::hir::def_id::CrateNum
|
||||
>
|
||||
>,
|
||||
[few] hir_forest: rustc::hir::map::Forest,
|
||||
[few] diagnostic_items: rustc_data_structures::fx::FxHashMap<
|
||||
syntax::symbol::Symbol,
|
||||
rustc::hir::def_id::DefId,
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ pub struct Map<'hir> {
|
|||
|
||||
map: HirEntryMap<'hir>,
|
||||
|
||||
definitions: &'hir Definitions,
|
||||
definitions: Definitions,
|
||||
|
||||
/// The reverse mapping of `node_to_hir_id`.
|
||||
hir_to_node_id: FxHashMap<HirId, NodeId>,
|
||||
|
|
@ -267,8 +267,8 @@ impl<'hir> Map<'hir> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn definitions(&self) -> &'hir Definitions {
|
||||
self.definitions
|
||||
pub fn definitions(&self) -> &Definitions {
|
||||
&self.definitions
|
||||
}
|
||||
|
||||
pub fn def_key(&self, def_id: DefId) -> DefKey {
|
||||
|
|
@ -1251,7 +1251,7 @@ impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } }
|
|||
pub fn map_crate<'hir>(sess: &crate::session::Session,
|
||||
cstore: &CrateStoreDyn,
|
||||
forest: &'hir Forest,
|
||||
definitions: &'hir Definitions)
|
||||
definitions: Definitions)
|
||||
-> Map<'hir> {
|
||||
let _prof_timer = sess.prof.generic_activity("build_hir_map");
|
||||
|
||||
|
|
@ -1260,7 +1260,7 @@ pub fn map_crate<'hir>(sess: &crate::session::Session,
|
|||
.map(|(node_id, &hir_id)| (hir_id, node_id)).collect();
|
||||
|
||||
let (map, crate_hash) = {
|
||||
let hcx = crate::ich::StableHashingContext::new(sess, &forest.krate, definitions, cstore);
|
||||
let hcx = crate::ich::StableHashingContext::new(sess, &forest.krate, &definitions, cstore);
|
||||
|
||||
let mut collector = NodeCollector::root(sess,
|
||||
&forest.krate,
|
||||
|
|
|
|||
|
|
@ -995,7 +995,7 @@ impl<'tcx> Deref for TyCtxt<'tcx> {
|
|||
}
|
||||
|
||||
pub struct GlobalCtxt<'tcx> {
|
||||
pub arena: WorkerLocal<Arena<'tcx>>,
|
||||
pub arena: &'tcx WorkerLocal<Arena<'tcx>>,
|
||||
|
||||
interners: CtxtInterners<'tcx>,
|
||||
|
||||
|
|
@ -1170,6 +1170,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
local_providers: ty::query::Providers<'tcx>,
|
||||
extern_providers: ty::query::Providers<'tcx>,
|
||||
arenas: &'tcx AllArenas,
|
||||
arena: &'tcx WorkerLocal<Arena<'tcx>>,
|
||||
resolutions: ty::ResolverOutputs,
|
||||
hir: hir_map::Map<'tcx>,
|
||||
on_disk_query_result_cache: query::OnDiskCache<'tcx>,
|
||||
|
|
@ -1225,7 +1226,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
sess: s,
|
||||
lint_store,
|
||||
cstore,
|
||||
arena: WorkerLocal::new(|_| Arena::default()),
|
||||
arena,
|
||||
interners,
|
||||
dep_graph,
|
||||
prof: s.prof.clone(),
|
||||
|
|
|
|||
|
|
@ -283,121 +283,128 @@ pub fn run_compiler(
|
|||
return sess.compile_status();
|
||||
}
|
||||
|
||||
compiler.parse()?;
|
||||
let linker = compiler.enter(|queries| {
|
||||
let early_exit = || sess.compile_status().map(|_| None);
|
||||
queries.parse()?;
|
||||
|
||||
if let Some(ppm) = &sess.opts.pretty {
|
||||
if ppm.needs_ast_map() {
|
||||
compiler.global_ctxt()?.peek_mut().enter(|tcx| {
|
||||
let expanded_crate = compiler.expansion()?.take().0;
|
||||
pretty::print_after_hir_lowering(
|
||||
tcx,
|
||||
compiler.input(),
|
||||
&expanded_crate,
|
||||
if let Some(ppm) = &sess.opts.pretty {
|
||||
if ppm.needs_ast_map() {
|
||||
queries.global_ctxt()?.peek_mut().enter(|tcx| {
|
||||
let expanded_crate = queries.expansion()?.take().0;
|
||||
pretty::print_after_hir_lowering(
|
||||
tcx,
|
||||
compiler.input(),
|
||||
&expanded_crate,
|
||||
*ppm,
|
||||
compiler.output_file().as_ref().map(|p| &**p),
|
||||
);
|
||||
Ok(())
|
||||
})?;
|
||||
} else {
|
||||
let krate = queries.parse()?.take();
|
||||
pretty::print_after_parsing(
|
||||
sess,
|
||||
&compiler.input(),
|
||||
&krate,
|
||||
*ppm,
|
||||
compiler.output_file().as_ref().map(|p| &**p),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
return early_exit();
|
||||
}
|
||||
|
||||
if callbacks.after_parsing(compiler) == Compilation::Stop {
|
||||
return early_exit();
|
||||
}
|
||||
|
||||
if sess.opts.debugging_opts.parse_only ||
|
||||
sess.opts.debugging_opts.show_span.is_some() ||
|
||||
sess.opts.debugging_opts.ast_json_noexpand {
|
||||
return early_exit();
|
||||
}
|
||||
|
||||
{
|
||||
let (_, lint_store) = &*queries.register_plugins()?.peek();
|
||||
|
||||
// Lint plugins are registered; now we can process command line flags.
|
||||
if sess.opts.describe_lints {
|
||||
describe_lints(&sess, &lint_store, true);
|
||||
return early_exit();
|
||||
}
|
||||
}
|
||||
|
||||
queries.expansion()?;
|
||||
if callbacks.after_expansion(compiler) == Compilation::Stop {
|
||||
return early_exit();
|
||||
}
|
||||
|
||||
queries.prepare_outputs()?;
|
||||
|
||||
if sess.opts.output_types.contains_key(&OutputType::DepInfo)
|
||||
&& sess.opts.output_types.len() == 1
|
||||
{
|
||||
return early_exit();
|
||||
}
|
||||
|
||||
queries.global_ctxt()?;
|
||||
|
||||
if sess.opts.debugging_opts.no_analysis ||
|
||||
sess.opts.debugging_opts.ast_json {
|
||||
return early_exit();
|
||||
}
|
||||
|
||||
if sess.opts.debugging_opts.save_analysis {
|
||||
let expanded_crate = &queries.expansion()?.peek().0;
|
||||
let crate_name = queries.crate_name()?.peek().clone();
|
||||
queries.global_ctxt()?.peek_mut().enter(|tcx| {
|
||||
let result = tcx.analysis(LOCAL_CRATE);
|
||||
|
||||
time(sess, "save analysis", || {
|
||||
save::process_crate(
|
||||
tcx,
|
||||
&expanded_crate,
|
||||
&crate_name,
|
||||
&compiler.input(),
|
||||
None,
|
||||
DumpHandler::new(
|
||||
compiler.output_dir().as_ref().map(|p| &**p), &crate_name
|
||||
)
|
||||
)
|
||||
});
|
||||
|
||||
result
|
||||
// AST will be dropped *after* the `after_analysis` callback
|
||||
// (needed by the RLS)
|
||||
})?;
|
||||
} else {
|
||||
let krate = compiler.parse()?.take();
|
||||
pretty::print_after_parsing(
|
||||
sess,
|
||||
&compiler.input(),
|
||||
&krate,
|
||||
*ppm,
|
||||
compiler.output_file().as_ref().map(|p| &**p),
|
||||
);
|
||||
// Drop AST after creating GlobalCtxt to free memory
|
||||
mem::drop(queries.expansion()?.take());
|
||||
}
|
||||
return sess.compile_status();
|
||||
}
|
||||
|
||||
if callbacks.after_parsing(compiler) == Compilation::Stop {
|
||||
return sess.compile_status();
|
||||
}
|
||||
queries.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?;
|
||||
|
||||
if sess.opts.debugging_opts.parse_only ||
|
||||
sess.opts.debugging_opts.show_span.is_some() ||
|
||||
sess.opts.debugging_opts.ast_json_noexpand {
|
||||
return sess.compile_status();
|
||||
}
|
||||
|
||||
{
|
||||
let (_, lint_store) = &*compiler.register_plugins()?.peek();
|
||||
|
||||
// Lint plugins are registered; now we can process command line flags.
|
||||
if sess.opts.describe_lints {
|
||||
describe_lints(&sess, &lint_store, true);
|
||||
return sess.compile_status();
|
||||
if callbacks.after_analysis(compiler) == Compilation::Stop {
|
||||
return early_exit();
|
||||
}
|
||||
|
||||
if sess.opts.debugging_opts.save_analysis {
|
||||
mem::drop(queries.expansion()?.take());
|
||||
}
|
||||
|
||||
queries.ongoing_codegen()?;
|
||||
|
||||
if sess.opts.debugging_opts.print_type_sizes {
|
||||
sess.code_stats.print_type_sizes();
|
||||
}
|
||||
|
||||
let linker = queries.linker()?;
|
||||
Ok(Some(linker))
|
||||
})?;
|
||||
|
||||
if let Some(linker) = linker {
|
||||
linker.link()?
|
||||
}
|
||||
|
||||
compiler.expansion()?;
|
||||
if callbacks.after_expansion(compiler) == Compilation::Stop {
|
||||
return sess.compile_status();
|
||||
}
|
||||
|
||||
compiler.prepare_outputs()?;
|
||||
|
||||
if sess.opts.output_types.contains_key(&OutputType::DepInfo)
|
||||
&& sess.opts.output_types.len() == 1
|
||||
{
|
||||
return sess.compile_status();
|
||||
}
|
||||
|
||||
compiler.global_ctxt()?;
|
||||
|
||||
if sess.opts.debugging_opts.no_analysis ||
|
||||
sess.opts.debugging_opts.ast_json {
|
||||
return sess.compile_status();
|
||||
}
|
||||
|
||||
if sess.opts.debugging_opts.save_analysis {
|
||||
let expanded_crate = &compiler.expansion()?.peek().0;
|
||||
let crate_name = compiler.crate_name()?.peek().clone();
|
||||
compiler.global_ctxt()?.peek_mut().enter(|tcx| {
|
||||
let result = tcx.analysis(LOCAL_CRATE);
|
||||
|
||||
time(sess, "save analysis", || {
|
||||
save::process_crate(
|
||||
tcx,
|
||||
&expanded_crate,
|
||||
&crate_name,
|
||||
&compiler.input(),
|
||||
None,
|
||||
DumpHandler::new(compiler.output_dir().as_ref().map(|p| &**p), &crate_name)
|
||||
)
|
||||
});
|
||||
|
||||
result
|
||||
// AST will be dropped *after* the `after_analysis` callback
|
||||
// (needed by the RLS)
|
||||
})?;
|
||||
} else {
|
||||
// Drop AST after creating GlobalCtxt to free memory
|
||||
mem::drop(compiler.expansion()?.take());
|
||||
}
|
||||
|
||||
compiler.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?;
|
||||
|
||||
if callbacks.after_analysis(compiler) == Compilation::Stop {
|
||||
return sess.compile_status();
|
||||
}
|
||||
|
||||
if sess.opts.debugging_opts.save_analysis {
|
||||
mem::drop(compiler.expansion()?.take());
|
||||
}
|
||||
|
||||
compiler.ongoing_codegen()?;
|
||||
|
||||
// Drop GlobalCtxt after starting codegen to free memory
|
||||
mem::drop(compiler.global_ctxt()?.take());
|
||||
|
||||
if sess.opts.debugging_opts.print_type_sizes {
|
||||
sess.code_stats.print_type_sizes();
|
||||
}
|
||||
|
||||
compiler.link()?;
|
||||
|
||||
if sess.opts.debugging_opts.perf_stats {
|
||||
sess.print_perf_stats();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use crate::queries::Queries;
|
||||
use crate::util;
|
||||
pub use crate::passes::BoxedResolver;
|
||||
|
||||
|
|
@ -36,7 +35,6 @@ pub struct Compiler {
|
|||
pub(crate) input_path: Option<PathBuf>,
|
||||
pub(crate) output_dir: Option<PathBuf>,
|
||||
pub(crate) output_file: Option<PathBuf>,
|
||||
pub(crate) queries: Queries,
|
||||
pub(crate) crate_name: Option<String>,
|
||||
pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut lint::LintStore) + Send + Sync>>,
|
||||
pub(crate) override_queries:
|
||||
|
|
@ -169,7 +167,6 @@ pub fn run_compiler_in_existing_thread_pool<R>(
|
|||
input_path: config.input_path,
|
||||
output_dir: config.output_dir,
|
||||
output_file: config.output_file,
|
||||
queries: Default::default(),
|
||||
crate_name: config.crate_name,
|
||||
register_lints: config.register_lints,
|
||||
override_queries: config.override_queries,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use crate::util;
|
|||
use crate::proc_macro_decls;
|
||||
|
||||
use log::{info, warn, log_enabled};
|
||||
use rustc::arena::Arena;
|
||||
use rustc::dep_graph::DepGraph;
|
||||
use rustc::hir;
|
||||
use rustc::hir::lowering::lower_crate;
|
||||
|
|
@ -22,7 +23,7 @@ use rustc_codegen_ssa::back::link::emit_metadata;
|
|||
use rustc_codegen_utils::codegen_backend::CodegenBackend;
|
||||
use rustc_codegen_utils::link::filename_for_metadata;
|
||||
use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel};
|
||||
use rustc_data_structures::sync::{Lrc, ParallelIterator, par_iter};
|
||||
use rustc_data_structures::sync::{Lrc, Once, ParallelIterator, par_iter, WorkerLocal};
|
||||
use rustc_errors::PResult;
|
||||
use rustc_incremental;
|
||||
use rustc_mir as mir;
|
||||
|
|
@ -739,93 +740,77 @@ pub fn default_provide_extern(providers: &mut ty::query::Providers<'_>) {
|
|||
rustc_codegen_ssa::provide_extern(providers);
|
||||
}
|
||||
|
||||
declare_box_region_type!(
|
||||
pub BoxedGlobalCtxt,
|
||||
for('tcx),
|
||||
(&'tcx GlobalCtxt<'tcx>) -> ((), ())
|
||||
);
|
||||
pub struct QueryContext<'tcx>(&'tcx GlobalCtxt<'tcx>);
|
||||
|
||||
impl BoxedGlobalCtxt {
|
||||
impl<'tcx> QueryContext<'tcx> {
|
||||
pub fn enter<F, R>(&mut self, f: F) -> R
|
||||
where
|
||||
F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> R,
|
||||
F: FnOnce(TyCtxt<'tcx>) -> R,
|
||||
{
|
||||
self.access(|gcx| ty::tls::enter_global(gcx, |tcx| f(tcx)))
|
||||
ty::tls::enter_global(self.0, |tcx| f(tcx))
|
||||
}
|
||||
|
||||
pub fn print_stats(&self) {
|
||||
self.0.queries.print_stats()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_global_ctxt(
|
||||
compiler: &Compiler,
|
||||
pub fn create_global_ctxt<'tcx>(
|
||||
compiler: &'tcx Compiler,
|
||||
lint_store: Lrc<lint::LintStore>,
|
||||
mut hir_forest: hir::map::Forest,
|
||||
hir_forest: &'tcx hir::map::Forest,
|
||||
mut resolver_outputs: ResolverOutputs,
|
||||
outputs: OutputFilenames,
|
||||
crate_name: &str,
|
||||
) -> BoxedGlobalCtxt {
|
||||
let sess = compiler.session().clone();
|
||||
let codegen_backend = compiler.codegen_backend().clone();
|
||||
let crate_name = crate_name.to_string();
|
||||
global_ctxt: &'tcx Once<GlobalCtxt<'tcx>>,
|
||||
all_arenas: &'tcx AllArenas,
|
||||
arena: &'tcx WorkerLocal<Arena<'tcx>>,
|
||||
) -> QueryContext<'tcx> {
|
||||
let sess = &compiler.session();
|
||||
let defs = mem::take(&mut resolver_outputs.definitions);
|
||||
let override_queries = compiler.override_queries;
|
||||
|
||||
let ((), result) = BoxedGlobalCtxt::new(static move || {
|
||||
let sess = &*sess;
|
||||
|
||||
let global_ctxt: Option<GlobalCtxt<'_>>;
|
||||
let arenas = AllArenas::new();
|
||||
|
||||
// Construct the HIR map.
|
||||
let hir_map = time(sess, "indexing HIR", || {
|
||||
hir::map::map_crate(sess, &*resolver_outputs.cstore, &mut hir_forest, &defs)
|
||||
});
|
||||
|
||||
let query_result_on_disk_cache = time(sess, "load query result cache", || {
|
||||
rustc_incremental::load_query_result_cache(sess)
|
||||
});
|
||||
|
||||
let mut local_providers = ty::query::Providers::default();
|
||||
default_provide(&mut local_providers);
|
||||
codegen_backend.provide(&mut local_providers);
|
||||
|
||||
let mut extern_providers = local_providers;
|
||||
default_provide_extern(&mut extern_providers);
|
||||
codegen_backend.provide_extern(&mut extern_providers);
|
||||
|
||||
if let Some(callback) = override_queries {
|
||||
callback(sess, &mut local_providers, &mut extern_providers);
|
||||
}
|
||||
|
||||
let gcx = TyCtxt::create_global_ctxt(
|
||||
sess,
|
||||
lint_store,
|
||||
local_providers,
|
||||
extern_providers,
|
||||
&arenas,
|
||||
resolver_outputs,
|
||||
hir_map,
|
||||
query_result_on_disk_cache,
|
||||
&crate_name,
|
||||
&outputs
|
||||
);
|
||||
|
||||
global_ctxt = Some(gcx);
|
||||
let gcx = global_ctxt.as_ref().unwrap();
|
||||
|
||||
ty::tls::enter_global(gcx, |tcx| {
|
||||
// Do some initialization of the DepGraph that can only be done with the
|
||||
// tcx available.
|
||||
time(tcx.sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx));
|
||||
});
|
||||
|
||||
yield BoxedGlobalCtxt::initial_yield(());
|
||||
box_region_allow_access!(for('tcx), (&'tcx GlobalCtxt<'tcx>), (gcx));
|
||||
|
||||
if sess.opts.debugging_opts.query_stats {
|
||||
gcx.queries.print_stats();
|
||||
}
|
||||
// Construct the HIR map.
|
||||
let hir_map = time(sess, "indexing HIR", || {
|
||||
hir::map::map_crate(sess, &*resolver_outputs.cstore, &hir_forest, defs)
|
||||
});
|
||||
|
||||
result
|
||||
let query_result_on_disk_cache = time(sess, "load query result cache", || {
|
||||
rustc_incremental::load_query_result_cache(sess)
|
||||
});
|
||||
|
||||
let codegen_backend = compiler.codegen_backend();
|
||||
let mut local_providers = ty::query::Providers::default();
|
||||
default_provide(&mut local_providers);
|
||||
codegen_backend.provide(&mut local_providers);
|
||||
|
||||
let mut extern_providers = local_providers;
|
||||
default_provide_extern(&mut extern_providers);
|
||||
codegen_backend.provide_extern(&mut extern_providers);
|
||||
|
||||
if let Some(callback) = compiler.override_queries {
|
||||
callback(sess, &mut local_providers, &mut extern_providers);
|
||||
}
|
||||
|
||||
let gcx = global_ctxt.init_locking(|| TyCtxt::create_global_ctxt(
|
||||
sess,
|
||||
lint_store,
|
||||
local_providers,
|
||||
extern_providers,
|
||||
&all_arenas,
|
||||
arena,
|
||||
resolver_outputs,
|
||||
hir_map,
|
||||
query_result_on_disk_cache,
|
||||
&crate_name,
|
||||
&outputs
|
||||
));
|
||||
|
||||
// Do some initialization of the DepGraph that can only be done with the tcx available.
|
||||
ty::tls::enter_global(&gcx, |tcx| {
|
||||
time(tcx.sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx));
|
||||
});
|
||||
|
||||
QueryContext(gcx)
|
||||
}
|
||||
|
||||
/// Runs the resolution, type-checking, region checking and other
|
||||
|
|
|
|||
|
|
@ -1,17 +1,19 @@
|
|||
use crate::interface::{Compiler, Result};
|
||||
use crate::passes::{self, BoxedResolver, BoxedGlobalCtxt};
|
||||
use crate::passes::{self, BoxedResolver, QueryContext};
|
||||
|
||||
use rustc_incremental::DepGraphFuture;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::sync::{Lrc, Once, WorkerLocal};
|
||||
use rustc_codegen_utils::codegen_backend::CodegenBackend;
|
||||
use rustc::session::config::{OutputFilenames, OutputType};
|
||||
use rustc::util::common::{time, ErrorReported};
|
||||
use rustc::arena::Arena;
|
||||
use rustc::hir;
|
||||
use rustc::lint;
|
||||
use rustc::session::Session;
|
||||
use rustc::lint::LintStore;
|
||||
use rustc::hir::def_id::LOCAL_CRATE;
|
||||
use rustc::ty::steal::Steal;
|
||||
use rustc::ty::ResolverOutputs;
|
||||
use rustc::ty::{AllArenas, ResolverOutputs, GlobalCtxt};
|
||||
use rustc::dep_graph::DepGraph;
|
||||
use std::cell::{Ref, RefMut, RefCell};
|
||||
use std::rc::Rc;
|
||||
|
|
@ -44,13 +46,6 @@ impl<T> Query<T> {
|
|||
.unwrap()
|
||||
}
|
||||
|
||||
/// Returns a stolen query result. Panics if there's already a result.
|
||||
pub fn give(&self, value: T) {
|
||||
let mut result = self.result.borrow_mut();
|
||||
assert!(result.is_none(), "a result already exists");
|
||||
*result = Some(Ok(value));
|
||||
}
|
||||
|
||||
/// Borrows the query result using the RefCell. Panics if the result is stolen.
|
||||
pub fn peek(&self) -> Ref<'_, T> {
|
||||
Ref::map(self.result.borrow(), |r| {
|
||||
|
|
@ -74,24 +69,54 @@ impl<T> Default for Query<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct Queries {
|
||||
pub struct Queries<'tcx> {
|
||||
compiler: &'tcx Compiler,
|
||||
gcx: Once<GlobalCtxt<'tcx>>,
|
||||
|
||||
all_arenas: AllArenas,
|
||||
arena: WorkerLocal<Arena<'tcx>>,
|
||||
|
||||
dep_graph_future: Query<Option<DepGraphFuture>>,
|
||||
parse: Query<ast::Crate>,
|
||||
crate_name: Query<String>,
|
||||
register_plugins: Query<(ast::Crate, Lrc<LintStore>)>,
|
||||
expansion: Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>,
|
||||
dep_graph: Query<DepGraph>,
|
||||
lower_to_hir: Query<(Steal<hir::map::Forest>, Steal<ResolverOutputs>)>,
|
||||
lower_to_hir: Query<(&'tcx hir::map::Forest, Steal<ResolverOutputs>)>,
|
||||
prepare_outputs: Query<OutputFilenames>,
|
||||
global_ctxt: Query<BoxedGlobalCtxt>,
|
||||
global_ctxt: Query<QueryContext<'tcx>>,
|
||||
ongoing_codegen: Query<Box<dyn Any>>,
|
||||
link: Query<()>,
|
||||
}
|
||||
|
||||
impl Compiler {
|
||||
impl<'tcx> Queries<'tcx> {
|
||||
pub fn new(compiler: &'tcx Compiler) -> Queries<'tcx> {
|
||||
Queries {
|
||||
compiler,
|
||||
gcx: Once::new(),
|
||||
all_arenas: AllArenas::new(),
|
||||
arena: WorkerLocal::new(|_| Arena::default()),
|
||||
dep_graph_future: Default::default(),
|
||||
parse: Default::default(),
|
||||
crate_name: Default::default(),
|
||||
register_plugins: Default::default(),
|
||||
expansion: Default::default(),
|
||||
dep_graph: Default::default(),
|
||||
lower_to_hir: Default::default(),
|
||||
prepare_outputs: Default::default(),
|
||||
global_ctxt: Default::default(),
|
||||
ongoing_codegen: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn session(&self) -> &Lrc<Session> {
|
||||
&self.compiler.sess
|
||||
}
|
||||
fn codegen_backend(&self) -> &Lrc<Box<dyn CodegenBackend>> {
|
||||
&self.compiler.codegen_backend()
|
||||
}
|
||||
|
||||
pub fn dep_graph_future(&self) -> Result<&Query<Option<DepGraphFuture>>> {
|
||||
self.queries.dep_graph_future.compute(|| {
|
||||
self.dep_graph_future.compute(|| {
|
||||
Ok(if self.session().opts.build_dep_graph() {
|
||||
Some(rustc_incremental::load_dep_graph(self.session()))
|
||||
} else {
|
||||
|
|
@ -101,8 +126,8 @@ impl Compiler {
|
|||
}
|
||||
|
||||
pub fn parse(&self) -> Result<&Query<ast::Crate>> {
|
||||
self.queries.parse.compute(|| {
|
||||
passes::parse(self.session(), &self.input).map_err(
|
||||
self.parse.compute(|| {
|
||||
passes::parse(self.session(), &self.compiler.input).map_err(
|
||||
|mut parse_error| {
|
||||
parse_error.emit();
|
||||
ErrorReported
|
||||
|
|
@ -112,7 +137,7 @@ impl Compiler {
|
|||
}
|
||||
|
||||
pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, Lrc<LintStore>)>> {
|
||||
self.queries.register_plugins.compute(|| {
|
||||
self.register_plugins.compute(|| {
|
||||
let crate_name = self.crate_name()?.peek().clone();
|
||||
let krate = self.parse()?.take();
|
||||
|
||||
|
|
@ -120,7 +145,7 @@ impl Compiler {
|
|||
let result = passes::register_plugins(
|
||||
self.session(),
|
||||
&*self.codegen_backend().metadata_loader(),
|
||||
self.register_lints
|
||||
self.compiler.register_lints
|
||||
.as_ref()
|
||||
.map(|p| &**p)
|
||||
.unwrap_or_else(|| empty),
|
||||
|
|
@ -140,8 +165,8 @@ impl Compiler {
|
|||
}
|
||||
|
||||
pub fn crate_name(&self) -> Result<&Query<String>> {
|
||||
self.queries.crate_name.compute(|| {
|
||||
Ok(match self.crate_name {
|
||||
self.crate_name.compute(|| {
|
||||
Ok(match self.compiler.crate_name {
|
||||
Some(ref crate_name) => crate_name.clone(),
|
||||
None => {
|
||||
let parse_result = self.parse()?;
|
||||
|
|
@ -149,7 +174,7 @@ impl Compiler {
|
|||
rustc_codegen_utils::link::find_crate_name(
|
||||
Some(self.session()),
|
||||
&krate.attrs,
|
||||
&self.input
|
||||
&self.compiler.input
|
||||
)
|
||||
}
|
||||
})
|
||||
|
|
@ -159,11 +184,11 @@ impl Compiler {
|
|||
pub fn expansion(
|
||||
&self
|
||||
) -> Result<&Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>> {
|
||||
self.queries.expansion.compute(|| {
|
||||
self.expansion.compute(|| {
|
||||
let crate_name = self.crate_name()?.peek().clone();
|
||||
let (krate, lint_store) = self.register_plugins()?.take();
|
||||
passes::configure_and_expand(
|
||||
self.sess.clone(),
|
||||
self.session().clone(),
|
||||
lint_store.clone(),
|
||||
self.codegen_backend().metadata_loader(),
|
||||
krate,
|
||||
|
|
@ -175,7 +200,7 @@ impl Compiler {
|
|||
}
|
||||
|
||||
pub fn dep_graph(&self) -> Result<&Query<DepGraph>> {
|
||||
self.queries.dep_graph.compute(|| {
|
||||
self.dep_graph.compute(|| {
|
||||
Ok(match self.dep_graph_future()?.take() {
|
||||
None => DepGraph::new_disabled(),
|
||||
Some(future) => {
|
||||
|
|
@ -192,15 +217,15 @@ impl Compiler {
|
|||
}
|
||||
|
||||
pub fn lower_to_hir(
|
||||
&self,
|
||||
) -> Result<&Query<(Steal<hir::map::Forest>, Steal<ResolverOutputs>)>> {
|
||||
self.queries.lower_to_hir.compute(|| {
|
||||
&'tcx self,
|
||||
) -> Result<&Query<(&'tcx hir::map::Forest, Steal<ResolverOutputs>)>> {
|
||||
self.lower_to_hir.compute(|| {
|
||||
let expansion_result = self.expansion()?;
|
||||
let peeked = expansion_result.peek();
|
||||
let krate = &peeked.0;
|
||||
let resolver = peeked.1.steal();
|
||||
let lint_store = &peeked.2;
|
||||
let hir = Steal::new(resolver.borrow_mut().access(|resolver| {
|
||||
let hir = resolver.borrow_mut().access(|resolver| {
|
||||
passes::lower_to_hir(
|
||||
self.session(),
|
||||
lint_store,
|
||||
|
|
@ -208,41 +233,47 @@ impl Compiler {
|
|||
&*self.dep_graph()?.peek(),
|
||||
&krate
|
||||
)
|
||||
})?);
|
||||
})?;
|
||||
let hir = self.arena.alloc(hir);
|
||||
Ok((hir, Steal::new(BoxedResolver::to_resolver_outputs(resolver))))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn prepare_outputs(&self) -> Result<&Query<OutputFilenames>> {
|
||||
self.queries.prepare_outputs.compute(|| {
|
||||
self.prepare_outputs.compute(|| {
|
||||
let expansion_result = self.expansion()?;
|
||||
let (krate, boxed_resolver, _) = &*expansion_result.peek();
|
||||
let crate_name = self.crate_name()?;
|
||||
let crate_name = crate_name.peek();
|
||||
passes::prepare_outputs(self.session(), self, &krate, &boxed_resolver, &crate_name)
|
||||
passes::prepare_outputs(
|
||||
self.session(), self.compiler, &krate, &boxed_resolver, &crate_name
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn global_ctxt(&self) -> Result<&Query<BoxedGlobalCtxt>> {
|
||||
self.queries.global_ctxt.compute(|| {
|
||||
pub fn global_ctxt(&'tcx self) -> Result<&Query<QueryContext<'tcx>>> {
|
||||
self.global_ctxt.compute(|| {
|
||||
let crate_name = self.crate_name()?.peek().clone();
|
||||
let outputs = self.prepare_outputs()?.peek().clone();
|
||||
let lint_store = self.expansion()?.peek().2.clone();
|
||||
let hir = self.lower_to_hir()?;
|
||||
let hir = hir.peek();
|
||||
let (hir_forest, resolver_outputs) = &*hir;
|
||||
let hir = self.lower_to_hir()?.peek();
|
||||
let (ref hir_forest, ref resolver_outputs) = &*hir;
|
||||
Ok(passes::create_global_ctxt(
|
||||
self,
|
||||
self.compiler,
|
||||
lint_store,
|
||||
hir_forest.steal(),
|
||||
hir_forest,
|
||||
resolver_outputs.steal(),
|
||||
outputs,
|
||||
&crate_name))
|
||||
&crate_name,
|
||||
&self.gcx,
|
||||
&self.all_arenas,
|
||||
&self.arena,
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ongoing_codegen(&self) -> Result<&Query<Box<dyn Any>>> {
|
||||
self.queries.ongoing_codegen.compute(|| {
|
||||
pub fn ongoing_codegen(&'tcx self) -> Result<&Query<Box<dyn Any>>> {
|
||||
self.ongoing_codegen.compute(|| {
|
||||
let outputs = self.prepare_outputs()?;
|
||||
self.global_ctxt()?.peek_mut().enter(|tcx| {
|
||||
tcx.analysis(LOCAL_CRATE).ok();
|
||||
|
|
@ -259,22 +290,58 @@ impl Compiler {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn link(&self) -> Result<&Query<()>> {
|
||||
self.queries.link.compute(|| {
|
||||
let sess = self.session();
|
||||
pub fn linker(&'tcx self) -> Result<Linker> {
|
||||
let dep_graph = self.dep_graph()?;
|
||||
let prepare_outputs = self.prepare_outputs()?;
|
||||
let ongoing_codegen = self.ongoing_codegen()?;
|
||||
|
||||
let ongoing_codegen = self.ongoing_codegen()?.take();
|
||||
let sess = self.session().clone();
|
||||
let codegen_backend = self.codegen_backend().clone();
|
||||
|
||||
self.codegen_backend().join_codegen_and_link(
|
||||
ongoing_codegen,
|
||||
sess,
|
||||
&*self.dep_graph()?.peek(),
|
||||
&*self.prepare_outputs()?.peek(),
|
||||
).map_err(|_| ErrorReported)?;
|
||||
|
||||
Ok(())
|
||||
Ok(Linker {
|
||||
sess,
|
||||
dep_graph: dep_graph.peek().clone(),
|
||||
prepare_outputs: prepare_outputs.take(),
|
||||
ongoing_codegen: ongoing_codegen.take(),
|
||||
codegen_backend,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Linker {
|
||||
sess: Lrc<Session>,
|
||||
dep_graph: DepGraph,
|
||||
prepare_outputs: OutputFilenames,
|
||||
ongoing_codegen: Box<dyn Any>,
|
||||
codegen_backend: Lrc<Box<dyn CodegenBackend>>,
|
||||
}
|
||||
|
||||
impl Linker {
|
||||
pub fn link(self) -> Result<()> {
|
||||
self.codegen_backend.join_codegen_and_link(
|
||||
self.ongoing_codegen,
|
||||
&self.sess,
|
||||
&self.dep_graph,
|
||||
&self.prepare_outputs,
|
||||
).map_err(|_| ErrorReported)
|
||||
}
|
||||
}
|
||||
|
||||
impl Compiler {
|
||||
pub fn enter<F, T>(&self, f: F) -> T
|
||||
where F: for<'tcx> FnOnce(&'tcx Queries<'tcx>) -> T
|
||||
{
|
||||
let queries = Queries::new(&self);
|
||||
let ret = f(&queries);
|
||||
|
||||
if self.session().opts.debugging_opts.query_stats {
|
||||
if let Ok(gcx) = queries.global_ctxt() {
|
||||
gcx.peek().print_stats();
|
||||
}
|
||||
}
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
// This method is different to all the other methods in `Compiler` because
|
||||
// it lacks a `Queries` entry. It's also not currently used. It does serve
|
||||
|
|
@ -282,24 +349,30 @@ impl Compiler {
|
|||
// between some passes. And see `rustc_driver::run_compiler` for a more
|
||||
// complex example.
|
||||
pub fn compile(&self) -> Result<()> {
|
||||
self.prepare_outputs()?;
|
||||
let linker = self.enter(|queries| {
|
||||
queries.prepare_outputs()?;
|
||||
|
||||
if self.session().opts.output_types.contains_key(&OutputType::DepInfo)
|
||||
&& self.session().opts.output_types.len() == 1
|
||||
{
|
||||
return Ok(())
|
||||
if self.session().opts.output_types.contains_key(&OutputType::DepInfo)
|
||||
&& self.session().opts.output_types.len() == 1
|
||||
{
|
||||
return Ok(None)
|
||||
}
|
||||
|
||||
queries.global_ctxt()?;
|
||||
|
||||
// Drop AST after creating GlobalCtxt to free memory.
|
||||
mem::drop(queries.expansion()?.take());
|
||||
|
||||
queries.ongoing_codegen()?;
|
||||
|
||||
let linker = queries.linker()?;
|
||||
Ok(Some(linker))
|
||||
})?;
|
||||
|
||||
if let Some(linker) = linker {
|
||||
linker.link()?
|
||||
}
|
||||
|
||||
self.global_ctxt()?;
|
||||
|
||||
// Drop AST after creating GlobalCtxt to free memory.
|
||||
mem::drop(self.expansion()?.take());
|
||||
|
||||
self.ongoing_codegen()?;
|
||||
|
||||
// Drop GlobalCtxt after starting codegen to free memory.
|
||||
mem::drop(self.global_ctxt()?.take());
|
||||
|
||||
self.link().map(|_| ())
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -343,14 +343,14 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
|
|||
registry: rustc_driver::diagnostics_registry(),
|
||||
};
|
||||
|
||||
interface::run_compiler_in_existing_thread_pool(config, |compiler| {
|
||||
interface::run_compiler_in_existing_thread_pool(config, |compiler| compiler.enter(|queries| {
|
||||
let sess = compiler.session();
|
||||
|
||||
// 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 = {
|
||||
let parts = abort_on_err(compiler.expansion(), sess).peek();
|
||||
let parts = abort_on_err(queries.expansion(), sess).peek();
|
||||
let resolver = parts.1.borrow();
|
||||
|
||||
// Before we actually clone it, let's force all the extern'd crates to
|
||||
|
|
@ -358,10 +358,11 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
|
|||
// 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)
|
||||
);
|
||||
resolver.resolve_str_path_error(
|
||||
DUMMY_SP, extern_name, TypeNS, CRATE_NODE_ID
|
||||
).unwrap_or_else(
|
||||
|()| panic!("Unable to resolve external crate {}", extern_name)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -373,7 +374,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
|
|||
sess.fatal("Compilation failed, aborting rustdoc");
|
||||
}
|
||||
|
||||
let mut global_ctxt = abort_on_err(compiler.global_ctxt(), sess).take();
|
||||
let mut global_ctxt = abort_on_err(queries.global_ctxt(), sess).take();
|
||||
|
||||
global_ctxt.enter(|tcx| {
|
||||
tcx.analysis(LOCAL_CRATE).ok();
|
||||
|
|
@ -447,8 +448,8 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
|
|||
},
|
||||
sym::plugins => {
|
||||
report_deprecated_attr("plugins = \"...\"", diag);
|
||||
eprintln!("WARNING: `#![doc(plugins = \"...\")]` no longer functions; \
|
||||
see CVE-2018-1000622");
|
||||
eprintln!("WARNING: `#![doc(plugins = \"...\")]` \
|
||||
no longer functions; see CVE-2018-1000622");
|
||||
continue
|
||||
},
|
||||
_ => continue,
|
||||
|
|
@ -486,7 +487,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
|
|||
|
||||
(krate, ctxt.renderinfo.into_inner(), render_options)
|
||||
})
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
/// `DefId` or parameter index (`ty::ParamTy.index`) of a synthetic type parameter
|
||||
|
|
|
|||
|
|
@ -85,14 +85,14 @@ pub fn run(options: Options) -> i32 {
|
|||
let mut test_args = options.test_args.clone();
|
||||
let display_warnings = options.display_warnings;
|
||||
|
||||
let tests = interface::run_compiler(config, |compiler| -> Result<_, ErrorReported> {
|
||||
let lower_to_hir = compiler.lower_to_hir()?;
|
||||
let tests = interface::run_compiler(config, |compiler| compiler.enter(|queries| {
|
||||
let lower_to_hir = queries.lower_to_hir()?;
|
||||
|
||||
let mut opts = scrape_test_config(lower_to_hir.peek().0.borrow().krate());
|
||||
let mut opts = scrape_test_config(lower_to_hir.peek().0.krate());
|
||||
opts.display_warnings |= options.display_warnings;
|
||||
let enable_per_target_ignores = options.enable_per_target_ignores;
|
||||
let mut collector = Collector::new(
|
||||
compiler.crate_name()?.peek().to_string(),
|
||||
queries.crate_name()?.peek().to_string(),
|
||||
options,
|
||||
false,
|
||||
opts,
|
||||
|
|
@ -101,7 +101,8 @@ pub fn run(options: Options) -> i32 {
|
|||
enable_per_target_ignores,
|
||||
);
|
||||
|
||||
let mut global_ctxt = compiler.global_ctxt()?.take();
|
||||
let mut global_ctxt = queries.global_ctxt()?.take();
|
||||
|
||||
global_ctxt.enter(|tcx| {
|
||||
let krate = tcx.hir().krate();
|
||||
let mut hir_collector = HirCollector {
|
||||
|
|
@ -116,8 +117,9 @@ pub fn run(options: Options) -> i32 {
|
|||
});
|
||||
});
|
||||
|
||||
Ok(collector.tests)
|
||||
}).expect("compiler aborted in rustdoc!");
|
||||
let ret : Result<_, ErrorReported> = Ok(collector.tests);
|
||||
ret
|
||||
})).expect("compiler aborted in rustdoc!");
|
||||
|
||||
test_args.insert(0, "rustdoctest".to_string());
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,11 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
|
|||
|
||||
interface::run_compiler(config, |compiler| {
|
||||
// This runs all the passes prior to linking, too.
|
||||
compiler.link().ok();
|
||||
let linker = compiler.enter(|queries| {
|
||||
queries.linker()
|
||||
});
|
||||
if let Ok(linker) = linker {
|
||||
linker.link();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue